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
= 8192;
501 strcpy(cdc
->cdc_ShellCon
, "CON:///130/HID Rocket Bay/CLOSE/AUTO/WAIT");
502 cdc
->cdc_PollingMode
= FALSE
;
503 cdc
->cdc_LLPortMode
[1] = 2;
504 cdc
->cdc_HIDCtrlOpen
= FALSE
;
505 strcpy(cdc
->cdc_HIDCtrlRexx
, "HIDCTRL");
506 strcpy(cdc
->cdc_HIDCtrlTitle
, "HID Control");
507 cdc
->cdc_LLRumblePort
= 2;
508 cdc
->cdc_TurboMouse
= 0;
510 nch
->nch_UsingDefaultCfg
= TRUE
;
511 /* try to load default config */
512 pic
= psdGetClsCfg(GM_UNIQUENAME(libname
));
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 count
= nhi
->nhi_MapSize
= (nhi
->nhi_LogicalMax
- nhi
->nhi_LogicalMin
)+1;
2853 usageptr
= nhi
->nhi_UsageMap
= psdAllocVec(sizeof(ULONG
) * count
);
2854 alistptr
= nhi
->nhi_ActionMap
= psdAllocVec(sizeof(struct List
) * count
);
2855 nhi
->nhi_Buffer
= psdAllocVec(2 * sizeof(LONG
) * nhi
->nhi_Count
);
2856 nhi
->nhi_OldBuffer
= &nhi
->nhi_Buffer
[nhi
->nhi_Count
];
2857 nhi
->nhi_PhysicalMin
= nch
->nch_HidGlobal
.nhg_PhysicalMin
;
2858 nhi
->nhi_PhysicalMax
= nch
->nch_HidGlobal
.nhg_PhysicalMax
;
2859 nhi
->nhi_UnitExp
= nch
->nch_HidGlobal
.nhg_UnitExp
;
2860 nhi
->nhi_Unit
= nch
->nch_HidGlobal
.nhg_Unit
;
2862 if(!(usageptr
&& alistptr
&& nhi
->nhi_Buffer
))
2864 psdFreeVec(usageptr
);
2865 psdFreeVec(alistptr
);
2866 psdFreeVec(nhi
->nhi_Buffer
);
2868 KPRINTF(10, ("Out of memory\n"));
2873 nhi
->nhi_Usage
= nhi
->nhi_DesignIndex
= nhi
->nhi_StringIndex
= HID_PARAM_UNDEF
;
2874 NewList(&nhi
->nhi_ActionList
);
2876 KPRINTF(1, ("New Array(%ld*%ld) Item: %ld.%ld (%ld-%ld)\n",
2877 nhi
->nhi_Count
, nhi
->nhi_MapSize
,
2878 nhi
->nhi_Offset
>>3, nhi
->nhi_Offset
& 7,
2879 nhi
->nhi_LogicalMin
, nhi
->nhi_LogicalMax
));
2881 nhi
->nhi_SameUsages
= TRUE
;
2884 nhu
= (struct NepHidUsage
*) nch
->nch_HidDesigns
.lh_Head
;
2885 if(nhu
->nhu_Node
.ln_Succ
)
2887 designid
= nhu
->nhu_Usage
++;
2888 if(nhu
->nhu_Usage
> nhu
->nhu_UsageMax
)
2890 Remove(&nhu
->nhu_Node
);
2894 nhu
= (struct NepHidUsage
*) nch
->nch_HidStrings
.lh_Head
;
2895 if(nhu
->nhu_Node
.ln_Succ
)
2897 stringid
= nhu
->nhu_Usage
++;
2898 if(nhu
->nhu_Usage
> nhu
->nhu_UsageMax
)
2900 Remove(&nhu
->nhu_Node
);
2904 nhu
= (struct NepHidUsage
*) nch
->nch_HidUsages
.lh_Head
;
2905 if(nhu
->nhu_Node
.ln_Succ
)
2907 usageid
= nhu
->nhu_Usage
++;
2908 if(nhu
->nhu_Usage
> nhu
->nhu_UsageMax
)
2910 KPRINTF(1, ("Removing usage %08lx\n", nhu
));
2911 Remove(&nhu
->nhu_Node
);
2916 // check if usages are all the same
2917 if(count
< nhi
->nhi_MapSize
)
2919 if(usageid
!= usageptr
[-1])
2921 nhi
->nhi_SameUsages
= FALSE
;
2925 *usageptr
++ = usageid
;
2930 if(nhi
->nhi_SameUsages
)
2932 // if it's all the same, we can assign a usage id to this array
2933 nhi
->nhi_Usage
= nhi
->nhi_UsageMap
[0];
2935 AddTail(&nhc
->nhc_Items
, &nhi
->nhi_Node
);
2937 } /* FIXME: Clean string/delimiter stack if no usage? */
2938 bitpos
+= nch
->nch_HidGlobal
.nhg_ReportSize
* nch
->nch_HidGlobal
.nhg_ReportCount
;
2943 nch
->nch_HidGlobal
.nhg_LogicalMin
= HID_PARAM_UNDEF
;
2947 nch
->nch_HidGlobal
.nhg_LogicalMax
= HID_PARAM_UNDEF
;
2952 case REPORT_MAIN_COLLECT
:
2954 struct NepHidUsage
*nhu
;
2955 struct NepHidCollection
*oldnhc
= nhc
;
2956 KPRINTF(1, ("Collection(%lx)\n", udata
));
2957 if((nhc
= psdAllocVec(sizeof(struct NepHidCollection
))))
2959 NewList(&nhc
->nhc_Items
);
2960 nhc
->nhc_Parent
= oldnhc
;
2961 nhu
= (struct NepHidUsage
*) nch
->nch_HidUsages
.lh_Head
;
2962 if(nhu
->nhu_Node
.ln_Succ
)
2964 nhc
->nhc_Usage
= nhu
->nhu_Usage
;
2965 nhc
->nhc_Name
= nGetUsageName(nch
, nhu
->nhu_Usage
);
2969 nhc
->nhc_Usage
= nhc
->nhc_Parent
->nhc_Usage
;
2970 nhc
->nhc_Name
= psdCopyStr(nhc
->nhc_Parent
->nhc_Name
);
2972 nhc
->nhc_Name
= psdCopyStr("Argl!");
2976 node
= nch
->nch_HidUsages
.lh_Head
;
2977 while(node
->ln_Succ
)
2979 KPRINTF(1, ("Removing usage %08lx\n", node
));
2982 node
= nch
->nch_HidUsages
.lh_Head
;
2988 case REPORT_MAIN_ENDCOLL
:
2989 KPRINTF(1, ("EndCollection(%lx)\n", udata
));
2992 /* Get rid of empty collection */
2993 //if(!nhc->nhc_Items.lh_Head->ln_Succ)
2994 if(0) /* don't do this, we might need the parent collection! */
2996 struct NepHidCollection
*oldnhc
= nhc
;
2997 KPRINTF(1, ("Deleting empty collection %lx (%s)\n", nhc
, nhc
->nhc_Name
));
2998 nhc
= nhc
->nhc_Parent
;
2999 psdFreeVec(oldnhc
->nhc_Name
);
3002 AddTail(&nhr
->nhr_Collections
, &nhc
->nhc_Node
);
3003 nhc
->nhc_Report
= nhr
;
3004 nhc
= nhc
->nhc_Parent
;
3010 KPRINTF(1, ("Reserved_%02lx(%lx)\n", itag
, data
));
3011 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
),
3012 "HID Error at %04lx: Reserved_MAIN_%02lx(%lx)", reportpos
, itag
, data
);
3013 nDebugReport(nch
, nhr
);
3017 /* Remove remaining usages */
3018 node
= nch
->nch_HidUsages
.lh_Head
;
3019 while(node
->ln_Succ
)
3021 KPRINTF(1, ("MainEnd: Removing usage %08lx\n", node
));
3024 node
= nch
->nch_HidUsages
.lh_Head
;
3026 /* Remove remaining designators */
3027 node
= nch
->nch_HidDesigns
.lh_Head
;
3028 while(node
->ln_Succ
)
3030 KPRINTF(1, ("MainEnd: Removing designator %08lx\n", node
));
3033 node
= nch
->nch_HidDesigns
.lh_Head
;
3035 /* Remove remaining strings */
3036 node
= nch
->nch_HidStrings
.lh_Head
;
3037 while(node
->ln_Succ
)
3039 KPRINTF(1, ("MainEnd: Removing strings %08lx\n", node
));
3042 node
= nch
->nch_HidStrings
.lh_Head
;
3047 case REPORT_MAIN_INPUT
:
3048 nhr
->nhr_ReportInSize
= bitpos
;
3050 case REPORT_MAIN_OUTPUT
:
3051 nhr
->nhr_ReportOutSize
= bitpos
;
3053 case REPORT_MAIN_FEATURE
:
3054 nhr
->nhr_ReportFeatSize
= bitpos
;
3060 case REPORT_ITYPE_GLOBAL
:
3061 //KPRINTF(1, ("Global "));
3064 case REPORT_GLOB_USAGE
:
3065 KPRINTF(1, ("Usage Page(%ld) %s\n", udata
, nNumToStr(nch
, NTS_USAGEPAGE
, udata
, "unknown")));
3066 nch
->nch_HidGlobal
.nhg_UsagePage
= udata
;
3069 case REPORT_GLOB_LOGMIN
:
3070 KPRINTF(1, ("LogMin(%ld)\n", data
));
3071 nch
->nch_HidGlobal
.nhg_LogicalMin
= data
;
3074 case REPORT_GLOB_LOGMAX
:
3075 KPRINTF(1, ("LogMax(%ld)\n", data
));
3076 nch
->nch_HidGlobal
.nhg_LogicalMax
= data
;
3079 case REPORT_GLOB_PHYMIN
:
3080 KPRINTF(1, ("PhyMin(%ld)\n", data
));
3081 nch
->nch_HidGlobal
.nhg_PhysicalMin
= data
;
3084 case REPORT_GLOB_PHYMAX
:
3085 KPRINTF(1, ("PhyMax(%ld)\n", data
));
3086 nch
->nch_HidGlobal
.nhg_PhysicalMax
= data
;
3089 case REPORT_GLOB_UNITEXP
:
3090 KPRINTF(1, ("UnitExp(%ld)\n", data
));
3091 nch
->nch_HidGlobal
.nhg_UnitExp
= data
;
3094 case REPORT_GLOB_UNIT
:
3095 KPRINTF(1, ("Unit(%ld)\n", data
));
3096 nch
->nch_HidGlobal
.nhg_Unit
= data
;
3099 case REPORT_GLOB_RPSIZE
:
3100 KPRINTF(1, ("ReportSize(%ld)\n", udata
));
3101 nch
->nch_HidGlobal
.nhg_ReportSize
= udata
;
3104 case REPORT_GLOB_RPID
:
3105 KPRINTF(1, ("ReportID(%ld)\n", udata
));
3106 nch
->nch_HidGlobal
.nhg_ReportID
= udata
;
3109 case REPORT_GLOB_RPCOUNT
:
3110 KPRINTF(1, ("ReportCount(%ld)\n", udata
));
3111 nch
->nch_HidGlobal
.nhg_ReportCount
= udata
;
3114 case REPORT_GLOB_PUSH
:
3116 struct NepHidGlobal
*nhg
= psdAllocVec(sizeof(struct NepHidGlobal
));
3117 KPRINTF(1, ("Push(%ld)\n", data
));
3120 *nhg
= nch
->nch_HidGlobal
;
3121 AddTail(&nch
->nch_HidStack
, &nhg
->nhg_Node
);
3123 KPRINTF(10, ("Out of HID stack memory!\n"));
3129 case REPORT_GLOB_POP
:
3131 struct NepHidGlobal
*nhg
= (struct NepHidGlobal
*) nch
->nch_HidStack
.lh_Tail
;
3132 KPRINTF(1, ("Pop(%ld)\n", data
));
3133 if(nhg
->nhg_Node
.ln_Pred
)
3135 nch
->nch_HidGlobal
= *nhg
;
3136 Remove(&nhg
->nhg_Node
);
3139 KPRINTF(10, ("Pop from HID stack without push!\n"));
3140 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
),
3141 "HID Error at %04lx: Pop from HID stack without push!", reportpos
);
3142 nDebugReport(nch
, nhr
);
3149 KPRINTF(1, ("Reserved_%02lx(%lx)\n", itag
, data
));
3150 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
),
3151 "HID Error at %04lx: Reserved_GLOBAL_%02lx(%lx)", reportpos
, itag
, data
);
3152 nDebugReport(nch
, nhr
);
3158 case REPORT_ITYPE_LOCAL
:
3159 //KPRINTF(1, ("Local "));
3162 case REPORT_LOCL_USAGE
:
3165 udata
|= nch
->nch_HidGlobal
.nhg_UsagePage
<<16;
3167 KPRINTF(1, ("Usage (%lx) %s\n", udata
, nNumToStr(nch
, NTS_USAGEID
, udata
, "unknown")));
3168 if(!nAddUsage(nch
, &nch
->nch_HidUsages
, udata
, udata
))
3174 case REPORT_LOCL_USEMIN
:
3177 udata
|= nch
->nch_HidGlobal
.nhg_UsagePage
<<16;
3179 KPRINTF(1, ("UsageMin (%lx) %s\n", udata
, nNumToStr(nch
, NTS_USAGEID
, udata
, "unknown")));
3181 if(usagemax
!= HID_PARAM_UNDEF
)
3183 if(!nAddUsage(nch
, &nch
->nch_HidUsages
, usagemin
, usagemax
))
3187 usagemin
= usagemax
= HID_PARAM_UNDEF
;
3191 case REPORT_LOCL_USEMAX
:
3194 udata
|= nch
->nch_HidGlobal
.nhg_UsagePage
<<16;
3196 KPRINTF(1, ("UsageMax (%lx) %s\n", udata
, nNumToStr(nch
, NTS_USAGEID
, udata
, "unknown")));
3198 if(usagemin
!= HID_PARAM_UNDEF
)
3200 if(!nAddUsage(nch
, &nch
->nch_HidUsages
, usagemin
, usagemax
))
3204 usagemin
= usagemax
= HID_PARAM_UNDEF
;
3208 case REPORT_LOCL_DESIDX
:
3209 KPRINTF(1, ("Designator index (%lx) %s\n", udata
, nNumToStr(nch
, NTS_USAGEID
, udata
, "unknown")));
3210 if(!nAddUsage(nch
, &nch
->nch_HidDesigns
, udata
, udata
))
3216 case REPORT_LOCL_DESMIN
:
3217 KPRINTF(1, ("DesignMin (%lx) %s\n", udata
, nNumToStr(nch
, NTS_USAGEID
, udata
, "unknown")));
3219 if(designmax
!= HID_PARAM_UNDEF
)
3221 if(!nAddUsage(nch
, &nch
->nch_HidDesigns
, designmin
, designmax
))
3225 designmin
= designmax
= HID_PARAM_UNDEF
;
3229 case REPORT_LOCL_DESMAX
:
3230 KPRINTF(1, ("DesignMax (%lx) %s\n", udata
, nNumToStr(nch
, NTS_USAGEID
, udata
, "unknown")));
3232 if(designmax
!= HID_PARAM_UNDEF
)
3234 if(!nAddUsage(nch
, &nch
->nch_HidDesigns
, designmin
, designmax
))
3238 designmin
= designmax
= HID_PARAM_UNDEF
;
3242 case REPORT_LOCL_STRIDX
:
3243 KPRINTF(1, ("String index (%lx) %s\n", udata
, nNumToStr(nch
, NTS_USAGEID
, udata
, "unknown")));
3244 if(!nAddUsage(nch
, &nch
->nch_HidStrings
, udata
, udata
))
3248 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
3249 "HID String Index %ld", udata
);
3252 case REPORT_LOCL_STRMIN
:
3253 KPRINTF(1, ("StringMin (%lx) %s\n", udata
, nNumToStr(nch
, NTS_USAGEID
, udata
, "unknown")));
3255 if(stringmax
!= HID_PARAM_UNDEF
)
3257 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
3258 "HID String Index Range %ld - %ld", stringmin
, stringmax
);
3259 if(!nAddUsage(nch
, &nch
->nch_HidStrings
, stringmin
, stringmax
))
3263 stringmin
= stringmax
= HID_PARAM_UNDEF
;
3267 case REPORT_LOCL_STRMAX
:
3268 KPRINTF(1, ("StringMax (%lx) %s\n", udata
, nNumToStr(nch
, NTS_USAGEID
, udata
, "unknown")));
3270 if(stringmin
!= HID_PARAM_UNDEF
)
3272 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
3273 "HID String Index Range %ld - %ld", stringmin
, stringmax
);
3274 if(!nAddUsage(nch
, &nch
->nch_HidStrings
, stringmin
, stringmax
))
3278 stringmin
= stringmax
= HID_PARAM_UNDEF
;
3282 case REPORT_LOCL_DELIM
:
3283 KPRINTF(1, ("Delimiter (%ld)\n", udata
));
3290 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "HID Report Delimiters not really supported!");
3294 KPRINTF(1, ("Reserved_%02lx(%lx)\n", itag
, udata
));
3295 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
),
3296 "HID Error at %04lx: Reserved_LOCAL_%02lx(%lx)", reportpos
, itag
, udata
);
3297 nDebugReport(nch
, nhr
);
3304 KPRINTF(1, ("Reserved!\n"));
3305 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
),
3306 "HID Error at %04lx: Reserved_%02lx", reportpos
, itag
);
3307 nDebugReport(nch
, nhr
);
3312 KPRINTF(1, ("Parsing done, status %lx.\n", rptr
));
3314 /* Remove remaining stack frame */
3315 node
= nch
->nch_HidStack
.lh_Head
;
3316 while(node
->ln_Succ
)
3318 KPRINTF(1, ("Removing stack frame %08lx\n", node
));
3321 node
= nch
->nch_HidStack
.lh_Head
;
3323 /* Remove remaining usages */
3324 node
= nch
->nch_HidUsages
.lh_Head
;
3325 while(node
->ln_Succ
)
3327 KPRINTF(1, ("Removing usage %08lx\n", node
));
3330 node
= nch
->nch_HidUsages
.lh_Head
;
3332 /* Remove remaining designators */
3333 node
= nch
->nch_HidDesigns
.lh_Head
;
3334 while(node
->ln_Succ
)
3336 KPRINTF(1, ("Removing designator %08lx\n", node
));
3339 node
= nch
->nch_HidDesigns
.lh_Head
;
3341 /* Remove remaining strings */
3342 node
= nch
->nch_HidStrings
.lh_Head
;
3343 while(node
->ln_Succ
)
3345 KPRINTF(1, ("Removing strings %08lx\n", node
));
3348 node
= nch
->nch_HidStrings
.lh_Head
;
3350 //nDebugReport(nch, nhr);
3351 return((BOOL
) (rptr
? TRUE
: FALSE
));
3355 /* /// "nFindCollID()" */
3356 BOOL
nFindCollID(struct NepClassHid
*nch
, struct NepHidCollection
*nhc
, ULONG collidmin
, ULONG collidmax
)
3360 if((nhc
->nhc_Usage
>= collidmin
) && (nhc
->nhc_Usage
<= collidmax
))
3364 } while((nhc
= nhc
->nhc_Parent
));
3369 /* /// "nFindItemID()" */
3370 struct NepHidItem
* nFindItemID(struct NepClassHid
*nch
, UWORD id
, UWORD itype
, ULONG
*pos
)
3372 struct NepHidReport
*nhr
= (struct NepHidReport
*) nch
->nch_HidReports
.lh_Head
;
3373 struct NepHidItem
*nhi
;
3374 struct NepHidItem
**nhiptr
;
3375 struct List
*alistptr
;
3380 if(itype
== REPORT_MAIN_OUTPUT
)
3384 else if(itype
== REPORT_MAIN_FEATURE
)
3390 while(nhr
->nhr_Node
.ln_Succ
)
3395 if((icount
= nhr
->nhr_FeatItemCount
))
3397 nhiptr
= nhr
->nhr_FeatItemMap
;
3400 if((icount
= nhr
->nhr_OutItemCount
))
3402 nhiptr
= nhr
->nhr_OutItemMap
;
3410 if(GET_WTYPE(&nhi
->nhi_ActionList
) == id
)
3415 if(!(nhi
->nhi_Flags
& RPF_MAIN_VARIABLE
))
3417 alistptr
= nhi
->nhi_ActionMap
;
3418 count
= nhi
->nhi_MapSize
;
3421 if(GET_WTYPE(alistptr
) == id
)
3423 *pos
= nhi
->nhi_MapSize
- count
;
3432 nhr
= (struct NepHidReport
*) nhr
->nhr_Node
.ln_Succ
;
3438 /* /// "nFindItemUsage()" */
3439 UWORD
nFindItemUsage(struct NepClassHid
*nch
, ULONG usage
, UWORD itype
)
3441 struct NepHidReport
*nhr
= (struct NepHidReport
*) nch
->nch_HidReports
.lh_Head
;
3442 struct NepHidItem
*nhi
;
3443 struct NepHidItem
**nhiptr
;
3445 struct List
*alistptr
;
3450 if(itype
== REPORT_MAIN_OUTPUT
)
3454 else if(itype
== REPORT_MAIN_FEATURE
)
3461 while(nhr
->nhr_Node
.ln_Succ
)
3466 if((icount
= nhr
->nhr_FeatItemCount
))
3468 nhiptr
= nhr
->nhr_FeatItemMap
;
3471 if((icount
= nhr
->nhr_OutItemCount
))
3473 nhiptr
= nhr
->nhr_OutItemMap
;
3481 if(nhi
->nhi_Usage
== usage
)
3483 return(GET_WTYPE(&nhi
->nhi_ActionList
));
3485 if(!(nhi
->nhi_Flags
& RPF_MAIN_VARIABLE
))
3487 usageptr
= nhi
->nhi_UsageMap
;
3488 alistptr
= nhi
->nhi_ActionMap
;
3489 count
= nhi
->nhi_MapSize
;
3492 if(*usageptr
== usage
)
3494 return GET_WTYPE(alistptr
);
3503 nhr
= (struct NepHidReport
*) nhr
->nhr_Node
.ln_Succ
;
3509 /* /// "UsbToPs2 Mapping" */
3510 const struct UsbToPs2Map usbtops2map
[] =
3512 { 0x010081, 0x5e }, // System Power Down
3513 { 0x010082, 0x5f }, // System Sleep
3514 { 0x010083, 0x63 }, // System Wake Up
3516 { 0x070046, 0x4c }, // Keyboard Print Screen
3517 { 0x070047, 0x64 }, // Keyboard Scroll Lock
3518 { 0x070048, 0x45 }, // Keyboard Pause
3519 { 0x070049, 0x0a }, // Keyboard Insert
3521 { 0x070066, 0x5e }, // Keyboard Power
3523 { 0x07007A, 0x08 }, // Keyboard Undo
3524 { 0x07007B, 0x17 }, // Keyboard Cut
3525 { 0x07007C, 0x18 }, // Keyboard Copy
3526 { 0x07007D, 0x0a }, // Keyboard Paste
3527 { 0x07007F, 0x20 }, // Keyboard Mute
3528 { 0x070080, 0x30 }, // Keyboard Volume Up
3529 { 0x070081, 0x2e }, // Keyboard Volume Down
3531 { 0x0C0030, 0x5e }, // Power
3532 { 0x0C0032, 0x5f }, // Sleep
3533 { 0x0C0033, 0x5f }, // Sleep After
3534 { 0x0C0034, 0x5f }, // Sleep Mode
3536 { 0x0C0094, 0x40 }, // Quit
3537 { 0x0C0095, 0x3b }, // Help
3538 { 0x0C00B0, 0x22 }, // Play
3539 { 0x0C00B1, 0x22 }, // Pause
3540 { 0x0C00B5, 0x19 }, // Scan Next Track
3541 { 0x0C00B6, 0x10 }, // Scan Previous Track
3542 { 0x0C00B7, 0x24 }, // Stop
3543 { 0x0C00CC, 0x24 }, // Stop/Eject
3544 { 0x0C00CD, 0x22 }, // Play/Pause
3545 { 0x0C00CE, 0x22 }, // Play/Skip
3547 { 0x0C00E2, 0x20 }, // Mute
3548 { 0x0C00E9, 0x30 }, // Volume Increment
3549 { 0x0C00EA, 0x2e }, // Volume Decrement
3551 { 0x0C0183, 0x6d }, // AL Consumer Control Configuration
3552 { 0x0C0184, 0x13 }, // AL Word Processor
3553 { 0x0C0185, 0x13 }, // AL Text Editor
3554 { 0x0C0186, 0x14 }, // AL Spreadsheet
3555 { 0x0C018A, 0x6c }, // AL Email Reader
3556 { 0x0C018F, 0x3d }, // AL Task/Project Manager
3557 { 0x0C0192, 0x21 }, // AL Calculator
3558 { 0x0C0194, 0x3c }, // AL Local Machine Browser
3559 { 0x0C0196, 0x3c }, // AL Internet Browser
3560 { 0x0C019B, 0x16 }, // AL Logon
3561 { 0x0C019C, 0x16 }, // AL Logoff
3562 { 0x0C019D, 0x16 }, // AL Logon/Logoff
3563 { 0x0C01A1, 0x3d }, // AL Process/Task Manager
3564 { 0x0C01A3, 0x1e }, // AL Next Task/Application
3565 { 0x0C01A4, 0x09 }, // AL Previous Task/Application
3566 { 0x0C01A6, 0x3b }, // AL Integrated Help Center
3567 { 0x0C01A7, 0x6b }, // AL Documents
3568 { 0x0C01A8, 0x23 }, // AL Thesaurus
3569 { 0x0C01A9, 0x23 }, // AL Dictionary
3570 { 0x0C01AB, 0x23 }, // AL Spell Check
3571 { 0x0C01AC, 0x23 }, // AL Grammar Check
3572 { 0x0C01B4, 0x05 }, // AL File Browser
3573 { 0x0C01BD, 0x3b }, // AL OEM Features/ Tips/Tutorial Browser
3574 { 0x0C01BE, 0x3b }, // AL OEM Help
3576 { 0x0C0201, 0x3e }, // AC New
3577 { 0x0C0202, 0x3f }, // AC Open
3578 { 0x0C0203, 0x40 }, // AC Close
3579 { 0x0C0204, 0x40 }, // AC Exit
3580 { 0x0C0207, 0x57 }, // AC Save
3581 { 0x0C0208, 0x58 }, // AC Print
3582 { 0x0C021A, 0x08 }, // AC Undo
3583 { 0x0C021B, 0x18 }, // AC Copy
3584 { 0x0C021C, 0x17 }, // AC Cut
3585 { 0x0C021D, 0x0a }, // AC Paste
3586 { 0x0C021F, 0x65 }, // AC Find
3587 { 0x0C0220, 0x65 }, // AC Find and Replace
3588 { 0x0C0221, 0x65 }, // AC Search
3589 { 0x0C0223, 0x32 }, // AC Home
3590 { 0x0C0224, 0x6a }, // AC Back
3591 { 0x0C0225, 0x69 }, // AC Forward
3592 { 0x0C0226, 0x68 }, // AC Stop
3593 { 0x0C0227, 0x67 }, // AC Refresh
3594 { 0x0C0228, 0x6a }, // AC Previous Link
3595 { 0x0C0229, 0x69 }, // AC Next Link
3596 { 0x0C022A, 0x66 }, // AC Bookmarks
3597 { 0x0C022B, 0x66 }, // AC History
3598 { 0x0C022C, 0x66 }, // AC Subscriptions
3599 { 0x0C0279, 0x07 }, // AC Redo/Repeat
3600 { 0x0C0288, 0x43 }, // AC Send To
3601 { 0x0C0289, 0x41 }, // AC Reply
3602 { 0x0C028A, 0x41 }, // AC Reply All
3603 { 0x0C028B, 0x42 }, // AC Forward Msg
3604 { 0x0C028C, 0x43 }, // AC Send
3610 /* /// "nDetectDefaultAction()" */
3611 BOOL
nDetectDefaultAction(struct NepClassHid
*nch
, struct NepHidItem
*nhi
, struct List
*lst
, struct NepHidCollection
*nhc
, ULONG uid
)
3614 UWORD usageid
= uid
;
3615 struct NepHidAction
*nha
;
3616 struct WacomCaps
*wc
;
3617 const struct UsbToPs2Map
*utp
= usbtops2map
;
3621 case 0x01: /* generic desktop page */
3622 if(usageid
== 0xfff0) /* extra init */
3624 /* AipTek USB Tablets Support */
3630 psdGetAttrs(PGA_DEVICE
, nch
->nch_Device
,
3631 DA_VendorID
, &vendid
,
3632 DA_ProductID
, &prodid
,
3634 if((vendid
== 0x08ca) &&
3635 ((prodid
== 0x0001) || (prodid
== 0x0010) ||
3636 ((prodid
>= 0x0020) && (prodid
<= 0x0024))) &&
3637 (!nhi
->nhi_ActionList
.lh_Head
->ln_Succ
))
3639 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
3640 "Generating special AipTek USB Tablet init sequence.");
3641 command
= nFindItemUsage(nch
, 0x0D003F, REPORT_MAIN_FEATURE
);
3642 data
= nFindItemUsage(nch
, 0x0D0040, REPORT_MAIN_FEATURE
);
3645 /* set resolution to 500DPI */
3646 if((nha
= nAllocAction(nch
, lst
, HUA_FEATURE
|HUA_ANY
)))
3648 nha
->nha_FeatOp
= HUAT_ASSIGN
;
3649 nha
->nha_FeatItem
= command
;
3650 nha
->nha_ValEnable
= TRUE
;
3651 nha
->nha_ValVar
= HUAT_CONST
;
3652 nha
->nha_ValConst
= 0x18;
3654 if((nha
= nAllocAction(nch
, lst
, HUA_FEATURE
|HUA_ANY
)))
3656 nha
->nha_FeatOp
= HUAT_ASSIGN
;
3657 nha
->nha_FeatItem
= data
;
3658 nha
->nha_ValEnable
= TRUE
;
3659 nha
->nha_ValVar
= HUAT_CONST
;
3660 nha
->nha_ValConst
= 0x04;
3662 if((nha
= nAllocAction(nch
, lst
, HUA_MISC
|HUA_ANY
)))
3664 nha
->nha_MiscMode
= HUAT_FLUSHEVENTS
;
3667 /* set absolute tablet mode */
3668 if((nha
= nAllocAction(nch
, lst
, HUA_FEATURE
|HUA_ANY
)))
3670 nha
->nha_FeatOp
= HUAT_ASSIGN
;
3671 nha
->nha_FeatItem
= command
;
3672 nha
->nha_ValEnable
= TRUE
;
3673 nha
->nha_ValVar
= HUAT_CONST
;
3674 nha
->nha_ValConst
= 0x10;
3676 if((nha
= nAllocAction(nch
, lst
, HUA_FEATURE
|HUA_ANY
)))
3678 nha
->nha_FeatOp
= HUAT_ASSIGN
;
3679 nha
->nha_FeatItem
= data
;
3680 nha
->nha_ValEnable
= TRUE
;
3681 nha
->nha_ValVar
= HUAT_CONST
;
3682 nha
->nha_ValConst
= 0x01;
3684 if((nha
= nAllocAction(nch
, lst
, HUA_MISC
|HUA_ANY
)))
3686 nha
->nha_MiscMode
= HUAT_FLUSHEVENTS
;
3689 /* enable macro keys */
3690 if((nha
= nAllocAction(nch
, lst
, HUA_FEATURE
|HUA_ANY
)))
3692 nha
->nha_FeatOp
= HUAT_ASSIGN
;
3693 nha
->nha_FeatItem
= command
;
3694 nha
->nha_ValEnable
= TRUE
;
3695 nha
->nha_ValVar
= HUAT_CONST
;
3696 nha
->nha_ValConst
= 0x11;
3698 if((nha
= nAllocAction(nch
, lst
, HUA_FEATURE
|HUA_ANY
)))
3700 nha
->nha_FeatOp
= HUAT_ASSIGN
;
3701 nha
->nha_FeatItem
= data
;
3702 nha
->nha_ValEnable
= TRUE
;
3703 nha
->nha_ValVar
= HUAT_CONST
;
3704 nha
->nha_ValConst
= 0x02;
3706 if((nha
= nAllocAction(nch
, lst
, HUA_MISC
|HUA_ANY
)))
3708 nha
->nha_MiscMode
= HUAT_FLUSHEVENTS
;
3711 /* enable auto gain */
3712 if((nha
= nAllocAction(nch
, lst
, HUA_FEATURE
|HUA_ANY
)))
3714 nha
->nha_FeatOp
= HUAT_ASSIGN
;
3715 nha
->nha_FeatItem
= command
;
3716 nha
->nha_ValEnable
= TRUE
;
3717 nha
->nha_ValVar
= HUAT_CONST
;
3718 nha
->nha_ValConst
= 0x12;
3720 if((nha
= nAllocAction(nch
, lst
, HUA_FEATURE
|HUA_ANY
)))
3722 nha
->nha_FeatOp
= HUAT_ASSIGN
;
3723 nha
->nha_FeatItem
= data
;
3724 nha
->nha_ValEnable
= TRUE
;
3725 nha
->nha_ValVar
= HUAT_CONST
;
3726 nha
->nha_ValConst
= 0xff;
3728 /*if((nha = nAllocAction(nch, lst, HUA_MISC|HUA_ANY)))
3730 nha->nha_MiscMode = HUAT_FLUSHEVENTS;
3733 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3734 "AipTek: No command (%ld) or data (%ld) feature!", command
, data
);
3737 if(vendid
== 0x056a)
3739 for(wc
= WacomCapsTable
; wc
->wc_ProdID
!= prodid
; wc
++)
3741 if(wc
->wc_ProdID
== 0xffff)
3752 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
3753 "Generating special Wacom USB Tablet init sequence.");
3754 command
= nFindItemUsage(nch
, 0xff000001, REPORT_MAIN_FEATURE
);
3757 /* activate returning of absolute tablet data */
3758 if((nha
= nAllocAction(nch
, lst
, HUA_FEATURE
|HUA_ANY
)))
3760 nha
->nha_FeatOp
= HUAT_ASSIGN
;
3761 nha
->nha_FeatItem
= command
;
3762 nha
->nha_ValEnable
= TRUE
;
3763 nha
->nha_ValVar
= HUAT_CONST
;
3764 nha
->nha_ValConst
= 0x02;
3766 if((nha
= nAllocAction(nch
, lst
, HUA_MISC
|HUA_ANY
)))
3768 nha
->nha_MiscMode
= HUAT_FLUSHEVENTS
;
3770 if((nha
= nAllocAction(nch
, lst
, HUA_FEATURE
|HUA_ANY
)))
3772 nha
->nha_FeatOp
= HUAT_ASSIGN
;
3773 nha
->nha_FeatItem
= command
;
3774 nha
->nha_ValEnable
= TRUE
;
3775 nha
->nha_ValVar
= HUAT_CONST
;
3776 nha
->nha_ValConst
= 0x02;
3781 if((vendid
== 0x046d) &&
3782 (!nhi
->nhi_ActionList
.lh_Head
->ln_Succ
))
3784 command
= nFindItemUsage(nch
, 0xff000001, REPORT_MAIN_OUTPUT
);
3787 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
3788 "Adding special HID2HCI Logitech Bluetooth init sequence, but deactivated!");
3789 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3790 "This init sequence would disable HID usage and enable pure Bluetooth use!");
3791 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3792 "If you want to use this dongle for Bluetooth, switch the NOP-Startup-Actions to type Output!");
3793 // send three commands to output report 0x10
3794 if((nha
= nAllocAction(nch
, lst
, HUA_NOP
|HUA_ANY
)))
3796 nha
->nha_OutItem
= command
;
3797 strcpy(nha
->nha_OutArray
, "0xff, 0x80, 0x80, 0x01, 0x00, 0x00");
3799 if((nha
= nAllocAction(nch
, lst
, HUA_MISC
|HUA_ANY
)))
3801 nha
->nha_MiscMode
= HUAT_FLUSHEVENTS
;
3803 if((nha
= nAllocAction(nch
, lst
, HUA_NOP
|HUA_ANY
)))
3805 nha
->nha_OutItem
= command
;
3806 strcpy(nha
->nha_OutArray
, "0xff, 0x80, 0x00, 0x00, 0x30, 0x00");
3808 if((nha
= nAllocAction(nch
, lst
, HUA_MISC
|HUA_ANY
)))
3810 nha
->nha_MiscMode
= HUAT_FLUSHEVENTS
;
3812 if((nha
= nAllocAction(nch
, lst
, HUA_NOP
|HUA_ANY
)))
3814 nha
->nha_OutItem
= command
;
3815 strcpy(nha
->nha_OutArray
, "0xff, 0x81, 0x80, 0x00, 0x00, 0x00");
3821 if(nFindCollID(nch
, nhc
, 0x010002, 0x010002) || /* Mice */
3822 nFindCollID(nch
, nhc
, 0x0d0001, 0x0d000d)) /* Tablets */
3826 case 0x30: /* Mouse X */
3827 if((nha
= nAllocAction(nch
, lst
, HUA_MOUSEPOS
|HUA_ALWAYS
)))
3829 if(nhi
->nhi_Flags
& RPF_MAIN_RELATIVE
)
3831 nha
->nha_MouseAxis
= HUAT_DELTAX
;
3833 nha
->nha_MouseAxis
= HUAT_ABSX
;
3834 nha
->nha_ClipEnable
= TRUE
;
3835 nha
->nha_ClipMin
= 5;
3836 nha
->nha_ClipMax
= 95;
3837 nha
->nha_ClipStretch
= TRUE
;
3842 case 0x31: /* Mouse Y */
3843 if((nha
= nAllocAction(nch
, lst
, HUA_MOUSEPOS
|HUA_ALWAYS
)))
3845 if(nhi
->nhi_Flags
& RPF_MAIN_RELATIVE
)
3847 nha
->nha_MouseAxis
= HUAT_DELTAY
;
3849 nha
->nha_MouseAxis
= HUAT_ABSY
;
3850 nha
->nha_ClipEnable
= TRUE
;
3851 nha
->nha_ClipMin
= 5;
3852 nha
->nha_ClipMax
= 95;
3853 nha
->nha_ClipStretch
= TRUE
;
3858 case 0x38: /* Wheel */
3859 if((nha
= nAllocAction(nch
, lst
, HUA_WHEEL
|HUA_ALWAYS
)))
3861 nha
->nha_WheelMode
= HUAT_DELTAY
;
3862 nha
->nha_WheelDist
= 1;
3868 if(nFindCollID(nch
, nhc
, 0x010004, 0x010005)) /* Joystick, Game Pad */
3872 case 0x39: /* Hatswitch */
3873 if((nha
= nAllocAction(nch
, lst
, HUA_DIGJOY
|HUA_NAN
)))
3875 nha
->nha_JoypadOp
= HUAT_CLEAR
;
3876 nha
->nha_JoypadFeat
= HUAT_HATSWITCH
;
3877 nha
->nha_JoypadPort
= 1;
3879 if((nha
= nAllocAction(nch
, lst
, HUA_DIGJOY
|HUA_ALWAYS
)))
3881 nha
->nha_JoypadOp
= HUAT_ASSIGN
;
3882 nha
->nha_JoypadFeat
= HUAT_HATSWITCH
;
3883 nha
->nha_JoypadPort
= 1;
3887 case 0x30: /* X axis */
3888 case 0x35: /* Z rotation */
3889 case 0x31: /* Y axis */
3890 case 0x32: /* Z axis */
3892 ULONG minpos
= ((nhi
->nhi_LogicalMax
- nhi
->nhi_LogicalMin
+ 1)>>2) + nhi
->nhi_LogicalMin
;
3893 ULONG maxpos
= (((nhi
->nhi_LogicalMax
- nhi
->nhi_LogicalMin
+ 1)*3)>>2) + nhi
->nhi_LogicalMin
;
3897 if((usageid
== 0x30) || (usageid
== 0x35))
3899 negaxis
= HUAT_LEFT
;
3900 posaxis
= HUAT_RIGHT
;
3901 alogaxis
= HUAT_ABSX
;
3904 posaxis
= HUAT_DOWN
;
3905 alogaxis
= HUAT_ABSY
;
3907 if((nha
= nAllocAction(nch
, lst
, HUA_DIGJOY
|HUA_ANY
)))
3909 nha
->nha_CCEnable
= TRUE
;
3910 nha
->nha_CCCond
= HUAT_GT
;
3911 nha
->nha_CCConst2
= minpos
;
3912 nha
->nha_JoypadOp
= HUAT_CLEAR
;
3913 nha
->nha_JoypadFeat
= negaxis
;
3914 nha
->nha_JoypadPort
= 1;
3916 if((nha
= nAllocAction(nch
, lst
, HUA_DIGJOY
|HUA_ANY
)))
3918 nha
->nha_CCEnable
= TRUE
;
3919 nha
->nha_CCCond
= HUAT_LE
;
3920 nha
->nha_CCConst2
= minpos
;
3921 nha
->nha_JoypadOp
= HUAT_SET
;
3922 nha
->nha_JoypadFeat
= negaxis
;
3923 nha
->nha_JoypadPort
= 1;
3925 if((nha
= nAllocAction(nch
, lst
, HUA_DIGJOY
|HUA_ANY
)))
3927 nha
->nha_CCEnable
= TRUE
;
3928 nha
->nha_CCCond
= HUAT_LT
;
3929 nha
->nha_CCConst2
= maxpos
;
3930 nha
->nha_JoypadOp
= HUAT_CLEAR
;
3931 nha
->nha_JoypadFeat
= posaxis
;
3932 nha
->nha_JoypadPort
= 1;
3934 if((nha
= nAllocAction(nch
, lst
, HUA_DIGJOY
|HUA_ANY
)))
3936 nha
->nha_CCEnable
= TRUE
;
3937 nha
->nha_CCCond
= HUAT_GE
;
3938 nha
->nha_CCConst2
= maxpos
;
3939 nha
->nha_JoypadOp
= HUAT_SET
;
3940 nha
->nha_JoypadFeat
= posaxis
;
3941 nha
->nha_JoypadPort
= 1;
3943 if((nha
= nAllocAction(nch
, lst
, HUA_ANALOGJOY
|HUA_ANY
)))
3945 nha
->nha_APadFeat
= alogaxis
;
3946 nha
->nha_JoypadPort
= 1;
3953 if(nFindCollID(nch
, nhc
, 0x010008, 0x010008) && (nhi
->nhi_Flags
& RPF_MAIN_RELATIVE
)) /* Multi-axis controller */
3957 case 0x30: /* Mouse X */
3958 if((nha
= nAllocAction(nch
, lst
, HUA_MOUSEPOS
|HUA_ALWAYS
)))
3960 nha
->nha_MouseAxis
= HUAT_DELTAX
;
3961 nha
->nha_ClipEnable
= TRUE
;
3962 nha
->nha_ClipMin
= 10;
3963 nha
->nha_ClipMax
= 45;
3964 nha
->nha_ClipStretch
= TRUE
;
3965 nha
->nha_ScaleEnable
= TRUE
;
3966 nha
->nha_ScaleMin
= -32;
3967 nha
->nha_ScaleMax
= 0;
3968 nha
->nha_CCEnable
= TRUE
;
3969 nha
->nha_CCVar1
= HUAT_OITEMVALUE
;
3970 nha
->nha_CCCond
= HUAT_LT
;
3971 nha
->nha_CCConst2
= 0;
3973 if((nha
= nAllocAction(nch
, lst
, HUA_MOUSEPOS
|HUA_ALWAYS
)))
3975 nha
->nha_MouseAxis
= HUAT_DELTAX
;
3976 nha
->nha_ClipEnable
= TRUE
;
3977 nha
->nha_ClipMin
= 55;
3978 nha
->nha_ClipMax
= 90;
3979 nha
->nha_ClipStretch
= TRUE
;
3980 nha
->nha_ScaleEnable
= TRUE
;
3981 nha
->nha_ScaleMin
= 0;
3982 nha
->nha_ScaleMax
= 32;
3983 nha
->nha_CCEnable
= TRUE
;
3984 nha
->nha_CCVar1
= HUAT_OITEMVALUE
;
3985 nha
->nha_CCCond
= HUAT_GT
;
3986 nha
->nha_CCConst2
= 0;
3990 case 0x31: /* Mouse Y */
3991 if((nha
= nAllocAction(nch
, lst
, HUA_MOUSEPOS
|HUA_ALWAYS
)))
3993 nha
->nha_MouseAxis
= HUAT_DELTAY
;
3994 nha
->nha_ClipEnable
= TRUE
;
3995 nha
->nha_ClipMin
= 10;
3996 nha
->nha_ClipMax
= 45;
3997 nha
->nha_ClipStretch
= TRUE
;
3998 nha
->nha_ScaleEnable
= TRUE
;
3999 nha
->nha_ScaleMin
= -32;
4000 nha
->nha_ScaleMax
= 0;
4001 nha
->nha_CCEnable
= TRUE
;
4002 nha
->nha_CCVar1
= HUAT_OITEMVALUE
;
4003 nha
->nha_CCCond
= HUAT_LT
;
4004 nha
->nha_CCConst2
= 0;
4006 if((nha
= nAllocAction(nch
, lst
, HUA_MOUSEPOS
|HUA_ALWAYS
)))
4008 nha
->nha_MouseAxis
= HUAT_DELTAY
;
4009 nha
->nha_ClipEnable
= TRUE
;
4010 nha
->nha_ClipMin
= 55;
4011 nha
->nha_ClipMax
= 90;
4012 nha
->nha_ClipStretch
= TRUE
;
4013 nha
->nha_ScaleEnable
= TRUE
;
4014 nha
->nha_ScaleMin
= 0;
4015 nha
->nha_ScaleMax
= 32;
4016 nha
->nha_CCEnable
= TRUE
;
4017 nha
->nha_CCVar1
= HUAT_OITEMVALUE
;
4018 nha
->nha_CCCond
= HUAT_GT
;
4019 nha
->nha_CCConst2
= 0;
4023 case 0x32: /* Mouse Z */
4025 LONG minpos
= (((nhi
->nhi_LogicalMax
- nhi
->nhi_LogicalMin
+ 1)*3)>>3) + nhi
->nhi_LogicalMin
;
4026 LONG maxpos
= (((nhi
->nhi_LogicalMax
- nhi
->nhi_LogicalMin
+ 1)*5)>>3) + nhi
->nhi_LogicalMin
;
4027 UWORD led
= nFindItemUsage(nch
, 0x08004B, REPORT_MAIN_OUTPUT
); // blue LED
4030 if((nha
= nAllocAction(nch
, lst
, HUA_BUTTONS
|HUA_ANY
)))
4032 nha
->nha_ButtonMode
= HUAT_SET
;
4033 nha
->nha_ButtonNo
= 1;
4034 nha
->nha_CCEnable
= TRUE
;
4035 nha
->nha_CCCond
= HUAT_GT
;
4036 nha
->nha_CCConst2
= maxpos
;
4038 if(led
&& ((nha
= nAllocAction(nch
, lst
, HUA_OUTPUT
|HUA_ANY
))))
4040 nha
->nha_OutOp
= HUAT_SET
;
4041 nha
->nha_OutItem
= led
;
4042 nha
->nha_CCEnable
= TRUE
;
4043 nha
->nha_CCCond
= HUAT_GT
;
4044 nha
->nha_CCConst2
= maxpos
;
4046 if((nha
= nAllocAction(nch
, lst
, HUA_BUTTONS
|HUA_ANY
)))
4048 nha
->nha_ButtonMode
= HUAT_CLEAR
;
4049 nha
->nha_ButtonNo
= 1;
4050 nha
->nha_CCEnable
= TRUE
;
4051 nha
->nha_CCCond
= HUAT_LT
;
4052 nha
->nha_CCConst2
= maxpos
;
4054 if(led
&& ((nha
= nAllocAction(nch
, lst
, HUA_OUTPUT
|HUA_ANY
))))
4056 nha
->nha_OutOp
= HUAT_CLEAR
;
4057 nha
->nha_OutItem
= led
;
4058 nha
->nha_CCEnable
= TRUE
;
4059 nha
->nha_CCCond
= HUAT_LT
;
4060 nha
->nha_CCConst2
= maxpos
;
4065 if((nha
= nAllocAction(nch
, lst
, HUA_BUTTONS
|HUA_ANY
)))
4067 nha
->nha_ButtonMode
= HUAT_SET
;
4068 nha
->nha_ButtonNo
= 2;
4069 nha
->nha_CCEnable
= TRUE
;
4070 nha
->nha_CCCond
= HUAT_LT
;
4071 nha
->nha_CCConst2
= minpos
;
4073 if((nha
= nAllocAction(nch
, lst
, HUA_BUTTONS
|HUA_ANY
)))
4075 nha
->nha_ButtonMode
= HUAT_CLEAR
;
4076 nha
->nha_ButtonNo
= 2;
4077 nha
->nha_CCEnable
= TRUE
;
4078 nha
->nha_CCCond
= HUAT_GT
;
4079 nha
->nha_CCConst2
= minpos
;
4085 case 0x35: /* Z rotation */
4087 LONG minpos
= (((nhi
->nhi_LogicalMax
- nhi
->nhi_LogicalMin
+ 1)*2)>>3) + nhi
->nhi_LogicalMin
;
4088 LONG maxpos
= (((nhi
->nhi_LogicalMax
- nhi
->nhi_LogicalMin
+ 1)*6)>>3) + nhi
->nhi_LogicalMin
;
4091 if((nha
= nAllocAction(nch
, lst
, HUA_WHEEL
|HUA_ANY
)))
4093 nha
->nha_WheelMode
= HUAT_DOWN
;
4094 nha
->nha_WheelDist
= 1;
4095 nha
->nha_CCEnable
= TRUE
;
4096 nha
->nha_CCCond
= HUAT_GT
;
4097 nha
->nha_CCConst2
= maxpos
;
4102 if((nha
= nAllocAction(nch
, lst
, HUA_WHEEL
|HUA_ANY
)))
4104 nha
->nha_WheelMode
= HUAT_UP
;
4105 nha
->nha_WheelDist
= 1;
4106 nha
->nha_CCEnable
= TRUE
;
4107 nha
->nha_CCCond
= HUAT_LT
;
4108 nha
->nha_CCConst2
= minpos
;
4117 case 0x09: /* Button page */
4118 if(nFindCollID(nch
, nhc
, 0x010002, 0x010002) || /* Mice */
4119 nFindCollID(nch
, nhc
, 0x0d0001, 0x0d000d) || /* Tablets */
4120 nFindCollID(nch
, nhc
, 0x010008, 0x010008)) /* Multi-Axis controller */
4122 if(usageid
&& (usageid
< 6))
4124 if((nha
= nAllocAction(nch
, lst
, HUA_BUTTONS
|HUA_ANY
)))
4126 nha
->nha_ButtonMode
= HUAT_ASSIGN
;
4127 nha
->nha_ButtonNo
= usageid
;
4131 if(nFindCollID(nch
, nhc
, 0x010004, 0x010005)) /* Joystick, Game Pad */
4133 if(usageid
&& (usageid
< 8))
4135 if((nha
= nAllocAction(nch
, lst
, HUA_DIGJOY
|HUA_ANY
)))
4137 nha
->nha_JoypadOp
= HUAT_ASSIGN
;
4138 nha
->nha_JoypadFeat
= HUAT_RED
+ usageid
- 1;
4139 nha
->nha_JoypadPort
= 1;
4145 case 0x07: /* keyboard page */
4148 case 0x39: /* Caps lock */
4151 if((nha
= nAllocAction(nch
, lst
, HUA_QUALIFIER
|HUA_DOWNEVENT
)))
4153 nha
->nha_QualMode
= HUAT_TOGGLE
;
4154 nha
->nha_Qualifier
= IEQUALIFIERB_CAPSLOCK
;
4156 if((led
= nFindItemUsage(nch
, 0x080002, REPORT_MAIN_OUTPUT
)))
4158 if((nha
= nAllocAction(nch
, lst
, HUA_OUTPUT
|HUA_DOWNEVENT
)))
4160 nha
->nha_OutOp
= HUAT_SET
;
4161 nha
->nha_OutItem
= led
;
4162 nha
->nha_CCEnable
= TRUE
;
4163 nha
->nha_CCVar1
= HUAT_QUALIFIERS
;
4164 nha
->nha_CCCond
= HUAT_BWAND
;
4165 nha
->nha_CCVar2
= HUAT_CONST
;
4166 nha
->nha_CCConst2
= IEQUALIFIER_CAPSLOCK
;
4168 if((nha
= nAllocAction(nch
, lst
, HUA_OUTPUT
|HUA_DOWNEVENT
)))
4170 nha
->nha_OutOp
= HUAT_CLEAR
;
4171 nha
->nha_OutItem
= led
;
4172 nha
->nha_CCEnable
= TRUE
;
4173 nha
->nha_CCVar1
= HUAT_QUALIFIERS
;
4174 nha
->nha_CCCond
= HUAT_BWNAND
;
4175 nha
->nha_CCVar2
= HUAT_CONST
;
4176 nha
->nha_CCConst2
= IEQUALIFIER_CAPSLOCK
;
4182 case 0xe0: /* Left control */
4183 if((nha
= nAllocAction(nch
, lst
, HUA_QUALIFIER
|HUA_ANY
)))
4185 nha
->nha_QualMode
= HUAT_ASSIGN
;
4186 nha
->nha_Qualifier
= IEQUALIFIERB_CONTROL
;
4190 case 0xe1: /* Left shift */
4191 if((nha
= nAllocAction(nch
, lst
, HUA_QUALIFIER
|HUA_ANY
)))
4193 nha
->nha_QualMode
= HUAT_ASSIGN
;
4194 nha
->nha_Qualifier
= IEQUALIFIERB_LSHIFT
;
4198 case 0xe2: /* Left alt */
4199 if((nha
= nAllocAction(nch
, lst
, HUA_QUALIFIER
|HUA_ANY
)))
4201 nha
->nha_QualMode
= HUAT_ASSIGN
;
4202 nha
->nha_Qualifier
= IEQUALIFIERB_LALT
;
4206 case 0xe3: /* Left GUI */
4207 if((nha
= nAllocAction(nch
, lst
, HUA_QUALIFIER
|HUA_ANY
)))
4209 nha
->nha_QualMode
= HUAT_ASSIGN
;
4210 nha
->nha_Qualifier
= IEQUALIFIERB_LCOMMAND
;
4214 case 0xe4: /* Right control */
4215 if((nha
= nAllocAction(nch
, lst
, HUA_QUALIFIER
|HUA_ANY
)))
4217 nha
->nha_QualMode
= HUAT_ASSIGN
;
4218 nha
->nha_Qualifier
= IEQUALIFIERB_CONTROL
;
4222 case 0xe5: /* Right shift */
4223 if((nha
= nAllocAction(nch
, lst
, HUA_QUALIFIER
|HUA_ANY
)))
4225 nha
->nha_QualMode
= HUAT_ASSIGN
;
4226 nha
->nha_Qualifier
= IEQUALIFIERB_RSHIFT
;
4230 case 0xe6: /* Right alt */
4231 if((nha
= nAllocAction(nch
, lst
, HUA_QUALIFIER
|HUA_ANY
)))
4233 nha
->nha_QualMode
= HUAT_ASSIGN
;
4234 nha
->nha_Qualifier
= IEQUALIFIERB_RALT
;
4238 case 0x45: /* F12 */
4239 case 0x65: /* Application */
4240 case 0xe7: /* Right GUI */
4241 if((nha
= nAllocAction(nch
, lst
, HUA_QUALIFIER
|HUA_ANY
)))
4243 nha
->nha_QualMode
= HUAT_ASSIGN
;
4244 nha
->nha_Qualifier
= IEQUALIFIERB_RCOMMAND
;
4248 nha
= nAllocAction(nch
, lst
, HUA_KEYMAP
|HUA_ANY
);
4251 case 0x0d: /* digitizer/tablet page */
4254 case 0x30: /* Tip pressure */
4255 case 0x31: /* Barrel pressure */
4256 if((nha
= nAllocAction(nch
, lst
, HUA_TABLET
|HUA_ALWAYS
)))
4258 nha
->nha_TabletAxis
= HUAT_PRESSURE
;
4262 case 0x32: /* In Range */
4263 case 0x37: /* Data Valid */
4264 if((nha
= nAllocAction(nch
, lst
, HUA_TABLET
|HUA_ALWAYS
)))
4266 nha
->nha_TabletAxis
= HUAT_PROX
;
4270 case 0x3D: /* X Tilt */
4271 if((nha
= nAllocAction(nch
, lst
, HUA_TABLET
|HUA_ALWAYS
)))
4273 nha
->nha_TabletAxis
= HUAT_XROT
;
4277 case 0x3E: /* Y Tilt */
4278 if((nha
= nAllocAction(nch
, lst
, HUA_TABLET
|HUA_ALWAYS
)))
4280 nha
->nha_TabletAxis
= HUAT_YROT
;
4284 case 0x42: /* Tip switch */
4285 if((nha
= nAllocAction(nch
, lst
, HUA_BUTTONS
|HUA_ANY
)))
4287 nha
->nha_ButtonMode
= HUAT_ASSIGN
;
4288 nha
->nha_ButtonNo
= 1;
4292 case 0x44: /* Barrel switch */
4293 if((nha
= nAllocAction(nch
, lst
, HUA_BUTTONS
|HUA_ANY
)))
4295 nha
->nha_ButtonMode
= HUAT_ASSIGN
;
4296 nha
->nha_ButtonNo
= 2;
4300 case 0x46: /* Tablet pick */
4301 if((nha
= nAllocAction(nch
, lst
, HUA_BUTTONS
|HUA_ANY
)))
4303 nha
->nha_ButtonMode
= HUAT_ASSIGN
;
4304 nha
->nha_ButtonNo
= 3;
4310 while(utp
->utp_UsageID
&& (utp
->utp_UsageID
<= uid
))
4312 if(utp
->utp_UsageID
== uid
)
4314 if((nha
= nAllocAction(nch
, lst
, HUA_EXTRAWKEY
|HUA_DOWNEVENT
)))
4316 nha
->nha_RawKey
= utp
->utp_ExtCode
;
4318 if((nha
= nAllocAction(nch
, lst
, HUA_EXTRAWKEY
|HUA_UPEVENT
)))
4320 nha
->nha_RawKey
= utp
->utp_ExtCode
|IECODE_UP_PREFIX
;
4329 /* /// "nCheckForDefaultAction()" */
4330 BOOL
nCheckForDefaultAction(struct NepClassHid
*nch
, struct NepHidItem
*nhi
, struct List
*lst
, struct NepHidCollection
*nhc
, ULONG uid
)
4333 struct NepHidAction
*nha
;
4334 struct NepHidAction
*nhadef
;
4335 struct List tmplist
;
4338 nDetectDefaultAction(nch
, nhi
, &tmplist
, nhc
, nhi
->nhi_Usage
);
4339 nha
= (struct NepHidAction
*) nhi
->nhi_ActionList
.lh_Head
;
4340 nhadef
= (struct NepHidAction
*) tmplist
.lh_Head
;
4341 while(nha
->nha_Node
.ln_Succ
)
4343 if(nhadef
->nha_Node
.ln_Succ
)
4345 nhadef
->nha_IsDefault
= nha
->nha_IsDefault
;
4346 if(memcmp(&nha
->nha_Type
, &nhadef
->nha_Type
, sizeof(struct NepHidAction
)-offsetof(struct NepHidAction
, nha_Type
)))
4348 nha
->nha_IsDefault
= FALSE
;
4351 nha
->nha_IsDefault
= TRUE
;
4353 nhadef
= (struct NepHidAction
*) nhadef
->nha_Node
.ln_Succ
;
4356 nha
->nha_IsDefault
= FALSE
;
4358 nha
= (struct NepHidAction
*) nha
->nha_Node
.ln_Succ
;
4360 nhadef
= (struct NepHidAction
*) tmplist
.lh_Head
;
4361 while(nhadef
->nha_Node
.ln_Succ
)
4363 Remove(&nhadef
->nha_Node
);
4365 nhadef
= (struct NepHidAction
*) tmplist
.lh_Head
;
4371 /* /// "nAllocAction()" */
4372 struct NepHidAction
* nAllocAction(struct NepClassHid
*nch
, struct List
*lst
, UWORD utype
)
4374 struct NepHidAction
*nha
= psdAllocVec(sizeof(struct NepHidAction
));
4377 KPRINTF(1, ("New action %lx\n", nha
));
4378 nha
->nha_Type
= utype
;
4379 nha
->nha_ButtonNo
= 1;
4380 nha
->nha_SoundVolume
= 64;
4381 nha
->nha_ClipMax
= 100;
4382 nha
->nha_CCVar1
= HUAT_EITEMVALUE
;
4383 nha
->nha_CCVar2
= HUAT_CONST
;
4384 AddTail(lst
, &nha
->nha_Node
);
4391 /* /// "nAddUsage()" */
4392 BOOL
nAddUsage(struct NepClassHid
*nch
, struct List
*list
, ULONG umin
, ULONG umax
)
4394 struct NepHidUsage
*nhu
;
4397 KPRINTF(10, ("UsageMin %lx > UsageMax %lx\n", umin
, umax
));
4400 if((nhu
= psdAllocVec(sizeof(struct NepHidUsage
))))
4402 AddTail(list
, &nhu
->nhu_Node
);
4403 nhu
->nhu_Usage
= umin
;
4404 nhu
->nhu_UsageMax
= umax
;
4407 KPRINTF(10, ("Out of memory during usage allocation.\n"));
4413 /* /// "nGetUsageName()" */
4414 STRPTR
nGetUsageName(struct NepClassHid
*nch
, ULONG uid
)
4418 uname
= nNumToStr(nch
, NTS_USAGEID
, uid
, NULL
);
4421 return(psdCopyStr(uname
));
4423 uname
= nNumToStr(nch
, NTS_USAGEPAGE
, uid
>>16, "unknown");
4424 return(psdCopyStrFmt("%s (0x%lx)", uname
, uid
));
4428 /* /// "nGenerateOutReport()" */
4429 void nGenerateOutReport(struct NepClassHid
*nch
, struct NepHidReport
*nhr
, UBYTE
*buf
)
4431 struct NepHidItem
**nhiptr
= nhr
->nhr_OutItemMap
;
4434 for(cnt
= 0; cnt
< nhr
->nhr_OutItemCount
; cnt
++)
4436 nEncodeItemBuffer(nch
, *nhiptr
++, buf
);
4441 /* /// "nGenerateFeatReport()" */
4442 void nGenerateFeatReport(struct NepClassHid
*nch
, struct NepHidReport
*nhr
, UBYTE
*buf
)
4444 struct NepHidItem
**nhiptr
= nhr
->nhr_FeatItemMap
;
4447 for(cnt
= 0; cnt
< nhr
->nhr_FeatItemCount
; cnt
++)
4449 nEncodeItemBuffer(nch
, *nhiptr
++, buf
);
4454 /* /// "nEncodeItemBuffer()" */
4455 void nEncodeItemBuffer(struct NepClassHid
*nch
, struct NepHidItem
*nhi
, UBYTE
*buf
)
4464 ioffset
= nhi
->nhi_Offset
;
4465 isize
= nhi
->nhi_Size
;
4466 if(nhi
->nhi_Flags
& RPF_MAIN_VARIABLE
)
4468 //KPRINTF(1, ("Processing var %08lx (%ld@%ld)...\n", nhi, isize, ioffset));
4469 value
= nhi
->nhi_OldValue
;
4470 if(value
< nhi
->nhi_LogicalMin
)
4472 value
= nhi
->nhi_LogicalMin
;
4474 else if(value
> nhi
->nhi_LogicalMax
)
4476 value
= nhi
->nhi_LogicalMax
;
4478 if(((ioffset
& 7) == 0) && (isize
== 8))
4480 buf
[ioffset
>>3] = value
;
4484 buf
[ioffset
>>3] &= ~(1UL<<(ioffset
& 7));
4487 buf
[ioffset
>>3] |= (1UL<<(ioffset
& 7));
4490 /* I know this routine is dead slow, but hopefully, this is only a very uncommon case */
4496 buf
[ioffset
>>3] &= ~(1UL<<(ioffset
& 7));
4499 buf
[ioffset
>>3] |= (1UL<<(ioffset
& 7));
4505 acount
= nhi
->nhi_Count
;
4506 KPRINTF(1, ("Processing arr %08lx (%ld@%ld) * %ld...\n", nhi
, isize
, ioffset
, acount
));
4507 /* first generate the values */
4508 valptr
= nhi
->nhi_Buffer
;
4509 if(((ioffset
& 7) == 0) && (isize
== 8))
4514 buf
[count
++] = *valptr
++;
4521 buf
[ioffset
>>3] &= ~(1UL<<(ioffset
& 7));
4524 buf
[ioffset
>>3] |= (1UL<<(ioffset
& 7));
4529 /* I know this routine is dead slow, but hopefully, this is only a very uncommon case */
4538 buf
[ioffset
>>3] &= ~(1UL<<(ioffset
& 7));
4541 buf
[ioffset
>>3] |= (1UL<<(ioffset
& 7));
4552 /* /// "nParseArrayString()" */
4553 void nParseArrayString(struct NepClassHid
*nch
, struct NepHidItem
*nhi
, STRPTR str
)
4556 LONG
*valptr
= nhi
->nhi_Buffer
;
4558 BOOL issigned
= FALSE
;
4562 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Parse error: Empty array value string not allowed.");
4565 acount
= nhi
->nhi_Count
;
4568 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Parse error: Target array has no space!");
4571 // mode == 0 -> start
4572 // mode == 1 -> decimal value
4573 // mode == 2 -> hex value
4574 // mode == 3 -> ascii character
4575 // mode == 4 -> string
4576 // mode == 5 -> waiting for termination
4578 while(*str
&& acount
)
4584 if((ch
== '0') && (*str
== 'x'))
4591 if((ch
>= '0') && (ch
<= '9'))
4618 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Parse error: Syntax error in S0!");
4621 case 1: // decimal value
4622 if((ch
>= '0') && (ch
<= '9'))
4627 *valptr
-= ch
- '0';
4629 *valptr
+= ch
- '0';
4645 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Parse error: Syntax error in S1!");
4648 case 2: // hex value
4649 if((ch
>= '0') && (ch
<= '9'))
4652 *valptr
+= ch
- '0';
4655 else if((ch
>= 'a') && (ch
<= 'f'))
4658 *valptr
+= ch
- 'a' + 10;
4661 else if((ch
>= 'A') && (ch
<= 'F'))
4664 *valptr
+= ch
- 'A' + 10;
4674 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Parse error: Syntax error in S2!");
4677 case 3: // ascii character
4685 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Parse error: Syntax error in S3!");
4698 case 5: // waiting for termination
4710 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Parse error: Syntax error in S5!");
4718 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Parse error: Syntax error in S3!");
4731 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Parse error: Excessive elements ignored!");
4736 /* /// "nProcessItem()" */
4737 BOOL
nProcessItem(struct NepClassHid
*nch
, struct NepHidItem
*nhi
, UBYTE
*buf
)
4742 ULONG ioffset
= nhi
->nhi_Offset
;
4743 ULONG isize
= nhi
->nhi_Size
;
4744 UBYTE
*bobuf
= &buf
[ioffset
>>3];
4749 BOOL bytealigned
= ((ioffset
& 7) == 0);
4750 struct NepHidAction
*nha
;
4752 if(nhi
->nhi_Flags
& RPF_MAIN_VARIABLE
)
4754 //KPRINTF(1, ("Processing var %08lx (%ld@%ld)...\n", nhi, isize, ioffset));
4755 if(bytealigned
&& (isize
== 8))
4757 if(nhi
->nhi_IsSigned
)
4759 value
= *((BYTE
*) bobuf
);
4766 value
= (buf
[ioffset
>>3]>>(ioffset
& 7)) & 1;
4768 else if(bytealigned
&& (isize
== 16))
4770 if(nhi
->nhi_IsSigned
)
4772 value
= (*bobuf
)|((((BYTE
*) bobuf
)[1])<<8);
4774 value
= (*bobuf
)|(bobuf
[1]<<8);
4777 else if(bytealigned
&& (isize
== 32))
4779 value
= bobuf
[0]|(bobuf
[1]<<8)|(bobuf
[2]<<16)|(bobuf
[3]<<24);
4781 /* I know this routine is dead slow, but hopefully, this is only a very uncommon case */
4785 if(nhi
->nhi_IsSigned
)
4789 if((buf
[ioffset
>>3]>>(ioffset
& 7)) & 1)
4798 value
|= (buf
[ioffset
>>3]>>(ioffset
& 7)) & 1;
4801 if((value
>= nhi
->nhi_LogicalMin
) && (value
<= nhi
->nhi_LogicalMax
))
4803 ULONG currmicros
= 0;
4805 if(nhi
->nhi_OldValue
!= value
)
4807 if((nhi
->nhi_Usage
> 0x070000) && (nhi
->nhi_Usage
< 0x0700E8))
4809 nch
->nch_LastUSBKey
= nhi
->nhi_Usage
;
4811 nch
->nch_LastItem
= nhi
;
4812 nch
->nch_LastItemAList
= &nhi
->nhi_ActionList
;
4815 if(nch
->nch_HIntBase
)
4817 CurrentTime(&currsecs
, &currmicros
);
4818 if(!DoubleClick(nhi
->nhi_LastSeconds
, nhi
->nhi_LastMicros
, currsecs
, currmicros
))
4820 nhi
->nhi_ClickCount
= 0;
4822 if(nhi
->nhi_OldValue
< value
)
4824 if(nhi
->nhi_LastSeconds
|| nhi
->nhi_LastMicros
)
4826 if(DoubleClick(nhi
->nhi_LastSeconds
, nhi
->nhi_LastMicros
, currsecs
, currmicros
))
4828 nhi
->nhi_ClickCount
++;
4830 nhi
->nhi_ClickCount
= 1;
4833 nhi
->nhi_ClickCount
= 1;
4835 nhi
->nhi_HoldSeconds
= nhi
->nhi_LastSeconds
= currsecs
;
4836 nhi
->nhi_HoldMicros
= nhi
->nhi_LastMicros
= currmicros
;
4839 /* no intuition library */
4840 nhi
->nhi_ClickCount
= 0;
4841 if(nhi
->nhi_OldValue
< value
)
4843 nhi
->nhi_ClickCount
= 1;
4846 nha
= (struct NepHidAction
*) nhi
->nhi_ActionList
.lh_Head
;
4847 while(nha
->nha_Node
.ln_Succ
)
4849 if((nhi
->nhi_OldValue
!= value
) || ((nha
->nha_Type
& HUA_TRIGMASK
) == HUA_ALWAYS
))
4851 nDoAction(nch
, nha
, nhi
, nhi
->nhi_Usage
, value
, (nhi
->nhi_OldValue
< value
) || ((nha
->nha_Type
& HUA_TRIGMASK
) == HUA_ALWAYS
));
4853 nha
= (struct NepHidAction
*) nha
->nha_Node
.ln_Succ
;
4855 if(nhi
->nhi_OldValue
> value
)
4857 nhi
->nhi_HoldSeconds
= 0;
4858 nhi
->nhi_HoldMicros
= 0;
4860 if((nhi
->nhi_OldValue
!= value
) && nch
->nch_ReportValues
&&
4861 nch
->nch_GUICurrentItem
&& (nch
->nch_GUICurrentItem
->nhgi_Item
== nhi
))
4863 nch
->nch_ItemChanged
= TRUE
;
4865 nhi
->nhi_OldValue
= value
;
4868 nha
= (struct NepHidAction
*) nhi
->nhi_ActionList
.lh_Head
;
4869 while(nha
->nha_Node
.ln_Succ
)
4871 if((nha
->nha_Type
& HUA_TRIGMASK
) == HUA_NAN
)
4873 nDoAction(nch
, nha
, nhi
, nhi
->nhi_Usage
, nhi
->nhi_OldValue
, 0);
4875 nha
= (struct NepHidAction
*) nha
->nha_Node
.ln_Succ
;
4879 nhi
->nhi_HoldSeconds
= nhi
->nhi_LastSeconds
= 0;
4880 nhi
->nhi_HoldMicros
= nhi
->nhi_LastMicros
= 0;
4881 acount
= nhi
->nhi_Count
;
4882 KPRINTF(1, ("Processing arr %08lx (%ld@%ld) * %ld...\n", nhi
, isize
, ioffset
, acount
));
4883 /* first generate the values */
4884 valptr
= nhi
->nhi_Buffer
;
4885 if(bytealigned
&& (isize
== 8))
4888 if(nhi
->nhi_IsSigned
)
4892 *valptr
++ = ((BYTE
*) buf
)[count
++];
4897 *valptr
++ = buf
[count
++];
4905 *valptr
++ = (buf
[ioffset
>>3]>>(ioffset
& 7)) & 1;
4909 /* I know this routine is dead slow, but hopefully, this is only a very uncommon case */
4915 if(nhi
->nhi_IsSigned
)
4919 if((buf
[ioffset
>>3]>>(ioffset
& 7)) & 1)
4928 value
|= (buf
[ioffset
>>3]>>(ioffset
& 7)) & 1;
4935 /* Look for up events first */
4939 value
= nhi
->nhi_OldBuffer
[acount
];
4940 if((value
>= nhi
->nhi_LogicalMin
) && (value
<= nhi
->nhi_LogicalMax
))
4942 valptr
= nhi
->nhi_Buffer
;
4943 count
= nhi
->nhi_Count
;
4947 if(*valptr
++ == value
)
4953 /* Not found in the new array, so generate up event */
4956 KPRINTF(1, ("Up event %ld\n", acount
));
4957 usage
= nhi
->nhi_UsageMap
[value
- nhi
->nhi_LogicalMin
];
4958 if(value
|| nhi
->nhi_LogicalMin
)
4960 nch
->nch_LastItem
= nhi
;
4961 nch
->nch_LastItemAList
= &nhi
->nhi_ActionMap
[value
- nhi
->nhi_LogicalMin
];
4963 nha
= (struct NepHidAction
*) nhi
->nhi_ActionMap
[value
- nhi
->nhi_LogicalMin
].lh_Head
;
4964 if(!nha
->nha_Node
.ln_Succ
) /* Use default, no override defined */
4966 nha
= (struct NepHidAction
*) nhi
->nhi_ActionList
.lh_Head
;
4968 nhi
->nhi_OldValue
= nhi
->nhi_LogicalMin
- 1;
4969 while(nha
->nha_Node
.ln_Succ
)
4971 nDoAction(nch
, nha
, nhi
, usage
, value
, FALSE
);
4972 nha
= (struct NepHidAction
*) nha
->nha_Node
.ln_Succ
;
4977 } while(++acount
< nhi
->nhi_Count
);
4979 /* Look for down events */
4983 value
= nhi
->nhi_Buffer
[acount
];
4984 //KPRINTF(1, ("[%ld] = %ld\n", acount, value));
4985 if((value
>= nhi
->nhi_LogicalMin
) && (value
<= nhi
->nhi_LogicalMax
))
4987 valptr
= nhi
->nhi_OldBuffer
;
4988 count
= nhi
->nhi_Count
;
4992 if(*valptr
++ == value
)
4998 /* Not found in the old array, so generate down event */
5001 KPRINTF(1, ("Down event %ld\n", acount
));
5002 usage
= nhi
->nhi_UsageMap
[value
- nhi
->nhi_LogicalMin
];
5003 if(value
|| nhi
->nhi_LogicalMin
)
5005 if((usage
> 0x070000) && (usage
< 0x0700E8))
5007 nch
->nch_LastUSBKey
= usage
;
5009 nch
->nch_LastItem
= nhi
;
5010 nch
->nch_LastItemAList
= &nhi
->nhi_ActionMap
[value
- nhi
->nhi_LogicalMin
];
5013 nha
= (struct NepHidAction
*) nhi
->nhi_ActionMap
[value
- nhi
->nhi_LogicalMin
].lh_Head
;
5014 if(!nha
->nha_Node
.ln_Succ
) /* Use default, no override defined */
5016 nha
= (struct NepHidAction
*) nhi
->nhi_ActionList
.lh_Head
;
5018 nhi
->nhi_OldValue
= nhi
->nhi_LogicalMin
- 1;
5019 while(nha
->nha_Node
.ln_Succ
)
5021 nDoAction(nch
, nha
, nhi
, usage
, value
, TRUE
);
5022 nha
= (struct NepHidAction
*) nha
->nha_Node
.ln_Succ
;
5027 } while(++acount
< nhi
->nhi_Count
);
5028 /* Copy new array */
5029 CopyMemQuick(nhi
->nhi_Buffer
, nhi
->nhi_OldBuffer
, sizeof(LONG
) * nhi
->nhi_Count
);
5035 static ULONG LLHatswitchEncoding
[8] = { JPF_JOY_UP
, JPF_JOY_UP
|JPF_JOY_RIGHT
, JPF_JOY_RIGHT
, JPF_JOY_RIGHT
|JPF_JOY_DOWN
,
5036 JPF_JOY_DOWN
, JPF_JOY_DOWN
|JPF_JOY_LEFT
, JPF_JOY_LEFT
, JPF_JOY_LEFT
|JPF_JOY_UP
};
5038 /* /// "nDoAction()" */
5039 BOOL
nDoAction(struct NepClassHid
*nch
, struct NepHidAction
*nha
, struct NepHidItem
*nhi
, ULONG uid
, LONG value
, BOOL downevent
)
5041 UWORD atype
= nha
->nha_Type
& HUA_ATYPEMASK
;
5044 LONG clipmin
, clipmax
;
5045 LONG origvalue
= value
;
5047 if(nch
->nch_DisableActions
)
5052 // bail out early as nothing below will affect this
5053 if(!(((nha
->nha_Type
& HUA_DOWNEVENT
) && downevent
) ||
5054 ((nha
->nha_Type
& HUA_UPEVENT
) && !downevent
) ||
5055 ((nha
->nha_Type
& HUA_TRIGMASK
) == HUA_ALWAYS
) ||
5056 ((nha
->nha_Type
& HUA_TRIGMASK
) == HUA_NAN
)))
5061 if(nha
->nha_AbsToRel
)
5063 value
= value
- nhi
->nhi_OldValue
;
5064 nhi
->nhi_RealMin
= nhi
->nhi_LogicalMin
- nhi
->nhi_LogicalMax
;
5065 nhi
->nhi_RealMax
= nhi
->nhi_LogicalMax
- nhi
->nhi_LogicalMin
;
5067 nhi
->nhi_RealMin
= nhi
->nhi_LogicalMin
;
5068 nhi
->nhi_RealMax
= nhi
->nhi_LogicalMax
;
5071 if(nha
->nha_ClipEnable
)
5073 if(nha
->nha_ClipMin
== nha
->nha_ClipMax
)
5075 /* shrink to a point */
5076 value
= ((nha
->nha_ClipMin
* (nhi
->nhi_RealMax
- nhi
->nhi_RealMin
)) / 100) + nhi
->nhi_RealMin
;
5078 if(nha
->nha_ClipMin
< nha
->nha_ClipMax
)
5080 /* normal clipping */
5081 clipmin
= ((nha
->nha_ClipMin
* (nhi
->nhi_RealMax
- nhi
->nhi_RealMin
)) / 100) + nhi
->nhi_RealMin
;
5082 clipmax
= ((nha
->nha_ClipMax
* (nhi
->nhi_RealMax
- nhi
->nhi_RealMin
)) / 100) + nhi
->nhi_RealMin
;
5084 /* inverse clipping */
5085 value
= nhi
->nhi_RealMax
- value
;
5086 clipmin
= ((nha
->nha_ClipMax
* (nhi
->nhi_RealMax
- nhi
->nhi_RealMin
)) / 100) + nhi
->nhi_RealMin
;
5087 clipmax
= ((nha
->nha_ClipMin
* (nhi
->nhi_RealMax
- nhi
->nhi_RealMin
)) / 100) + nhi
->nhi_RealMin
;
5098 if(nha
->nha_ClipStretch
&& (clipmax
- clipmin
))
5100 value
= (((value
- clipmin
) * (nhi
->nhi_RealMax
- nhi
->nhi_RealMin
)) /
5101 (clipmax
- clipmin
)) + nhi
->nhi_RealMin
;
5106 if(nha
->nha_ScaleEnable
&& (nha
->nha_ScaleMax
!= nha
->nha_ScaleMin
))
5108 value
= (((value
- nhi
->nhi_RealMin
) * (nha
->nha_ScaleMax
- nha
->nha_ScaleMin
)) /
5109 (nhi
->nhi_RealMax
- nhi
->nhi_RealMin
)) + nha
->nha_ScaleMin
;
5110 nhi
->nhi_RealMin
= nha
->nha_ScaleMin
;
5111 nhi
->nhi_RealMax
= nha
->nha_ScaleMax
;
5114 if(nha
->nha_CCEnable
)
5120 switch(nha
->nha_CCVar1
)
5122 case HUAT_EITEMVALUE
:
5126 case HUAT_OITEMVALUE
:
5131 var1
= nha
->nha_CCConst1
;
5134 case HUAT_CLICKCOUNT
:
5135 var1
= nhi
->nhi_ClickCount
;
5138 case HUAT_CLICKTIME
:
5143 if(nhi
->nhi_HoldSeconds
|| nhi
->nhi_HoldMicros
)
5145 CurrentTime(&currsecs
, &currmicros
);
5146 var1
= (currsecs
- nhi
->nhi_HoldSeconds
) * 1000;
5147 if(nhi
->nhi_HoldMicros
<= currmicros
)
5149 var1
+= (currmicros
- nhi
->nhi_HoldMicros
) / 1000;
5151 var1
-= (nhi
->nhi_HoldMicros
- currmicros
) / 1000;
5159 case HUAT_QUALIFIERS
:
5160 var1
= nch
->nch_KeyQualifiers
;
5164 var1
= nch
->nch_KeyQualifiers
|PeekQualifier();
5167 case HUAT_RANDOMBIT
:
5168 var1
= _rand(nch
->nch_ClsBase
) & 1;
5171 case HUAT_RANDOMVAL
:
5172 var1
= _rand(nch
->nch_ClsBase
);
5180 CurrentTime(&currsecs
, &currmicros
);
5181 var1
= (currsecs
* 1000) + (currmicros
/ 1000);
5185 case HUAT_LOCALVAR1
:
5186 case HUAT_LOCALVAR2
:
5187 case HUAT_LOCALVAR3
:
5188 case HUAT_LOCALVAR4
:
5189 case HUAT_LOCALVAR5
:
5190 case HUAT_LOCALVAR6
:
5191 case HUAT_LOCALVAR7
:
5192 case HUAT_LOCALVAR8
:
5193 var1
= nch
->nch_LocalVars
[nha
->nha_CCVar1
- HUAT_LOCALVAR1
];
5204 var1
= nch
->nch_ClsBase
->nh_GlobalVars
[nha
->nha_CCVar1
- HUAT_GLOBVARA
];
5207 switch(nha
->nha_CCVar2
)
5209 case HUAT_EITEMVALUE
:
5213 case HUAT_OITEMVALUE
:
5218 var2
= nha
->nha_CCConst2
;
5221 case HUAT_CLICKCOUNT
:
5222 var2
= nhi
->nhi_ClickCount
;
5225 case HUAT_CLICKTIME
:
5230 if(nhi
->nhi_HoldSeconds
|| nhi
->nhi_HoldMicros
)
5232 CurrentTime(&currsecs
, &currmicros
);
5233 var2
= (currsecs
- nhi
->nhi_HoldSeconds
) * 1000;
5234 if(nhi
->nhi_HoldMicros
<= currmicros
)
5236 var2
+= (currmicros
- nhi
->nhi_HoldMicros
) / 1000;
5238 var2
-= (nhi
->nhi_HoldMicros
- currmicros
) / 1000;
5246 case HUAT_QUALIFIERS
:
5247 var2
= nch
->nch_KeyQualifiers
;
5251 var2
= nch
->nch_KeyQualifiers
|PeekQualifier();
5254 case HUAT_RANDOMBIT
:
5255 var2
= _rand(nch
->nch_ClsBase
) & 1;
5258 case HUAT_RANDOMVAL
:
5259 var2
= _rand(nch
->nch_ClsBase
);
5267 CurrentTime(&currsecs
, &currmicros
);
5268 var2
= (currsecs
* 1000) + (currmicros
/ 1000);
5272 case HUAT_LOCALVAR1
:
5273 case HUAT_LOCALVAR2
:
5274 case HUAT_LOCALVAR3
:
5275 case HUAT_LOCALVAR4
:
5276 case HUAT_LOCALVAR5
:
5277 case HUAT_LOCALVAR6
:
5278 case HUAT_LOCALVAR7
:
5279 case HUAT_LOCALVAR8
:
5280 var2
= nch
->nch_LocalVars
[nha
->nha_CCVar2
- HUAT_LOCALVAR1
];
5291 var2
= nch
->nch_ClsBase
->nh_GlobalVars
[nha
->nha_CCVar2
- HUAT_GLOBVARA
];
5294 switch(nha
->nha_CCCond
)
5297 cond
= (var1
== var2
);
5301 cond
= (var1
!= var2
);
5305 cond
= (var1
< var2
);
5309 cond
= (var1
<= var2
);
5313 cond
= (var1
> var2
);
5317 cond
= (var1
>= var2
);
5321 cond
= (var1
&& var2
);
5325 cond
= !(var1
&& var2
);
5329 cond
= (var1
|| var2
);
5333 cond
= (var1
&& (!var2
)) || ((!var1
) && var2
);
5337 cond
= (var1
&& (!var2
));
5341 cond
= (var1
& var2
) ? TRUE
: FALSE
;
5345 cond
= (var1
& var2
) ? FALSE
: TRUE
;
5349 cond
= (var1
| var2
) ? TRUE
: FALSE
;
5353 cond
= (var1
^ var2
) ? TRUE
: FALSE
;
5357 cond
= (var1
& (~var2
)) ? TRUE
: FALSE
;
5367 if(nha
->nha_ValEnable
)
5369 switch(nha
->nha_ValVar
)
5371 case HUAT_EITEMVALUE
:
5375 case HUAT_OITEMVALUE
:
5380 value
= nha
->nha_ValConst
;
5383 case HUAT_CLICKCOUNT
:
5384 value
= nhi
->nhi_ClickCount
;
5387 case HUAT_CLICKTIME
:
5392 if(nhi
->nhi_HoldSeconds
|| nhi
->nhi_HoldMicros
)
5394 CurrentTime(&currsecs
, &currmicros
);
5395 value
= (currsecs
- nhi
->nhi_HoldSeconds
) * 1000;
5396 if(nhi
->nhi_HoldMicros
<= currmicros
)
5398 value
+= (currmicros
- nhi
->nhi_HoldMicros
) / 1000;
5400 value
-= (nhi
->nhi_HoldMicros
- currmicros
) / 1000;
5408 case HUAT_QUALIFIERS
:
5409 value
= nch
->nch_KeyQualifiers
;
5413 value
= nch
->nch_KeyQualifiers
|PeekQualifier();
5416 case HUAT_RANDOMBIT
:
5417 value
= _rand(nch
->nch_ClsBase
) & 1;
5420 case HUAT_RANDOMVAL
:
5421 value
= _rand(nch
->nch_ClsBase
);
5429 CurrentTime(&currsecs
, &currmicros
);
5430 value
= (currsecs
* 1000) + (currmicros
/ 1000);
5434 case HUAT_LOCALVAR1
:
5435 case HUAT_LOCALVAR2
:
5436 case HUAT_LOCALVAR3
:
5437 case HUAT_LOCALVAR4
:
5438 case HUAT_LOCALVAR5
:
5439 case HUAT_LOCALVAR6
:
5440 case HUAT_LOCALVAR7
:
5441 case HUAT_LOCALVAR8
:
5442 value
= nch
->nch_LocalVars
[nha
->nha_ValVar
- HUAT_LOCALVAR1
];
5453 value
= nch
->nch_ClsBase
->nh_GlobalVars
[nha
->nha_ValVar
- HUAT_GLOBVARA
];
5457 //KPRINTF(1, ("Call for action(%04lx) %lx = %ld %s\n", atype, uid, value, downevent ? "down" : "up"));
5465 struct ActionMsg
*am
;
5466 if(!nch
->nch_ClsBase
->nh_DTaskMsgPort
)
5468 nInstallLastActionHero(nch
);
5470 if(nch
->nch_ClsBase
->nh_DTaskMsgPort
)
5472 if((am
= AllocVec(sizeof(struct ActionMsg
), MEMF_PUBLIC
)))
5474 am
->am_Msg
.mn_Length
= sizeof(struct ActionMsg
);
5475 am
->am_Msg
.mn_ReplyPort
= NULL
;
5477 am
->am_Action
= nha
;
5478 PutMsg(nch
->nch_ClsBase
->nh_DTaskMsgPort
, &am
->am_Msg
);
5485 nSendRawKey(nch
, nha
->nha_RawKey
);
5491 if((uid
> 0x70000) && (uid
< 0x700e8))
5493 iecode
= nch
->nch_KeymapCfg
.kmc_Keymap
[uid
& 0xff];
5494 KPRINTF(1,("Key %ld %s\n", iecode
, downevent
? "DOWN" : "UP"));
5495 nch
->nch_FakeEvent
.ie_Class
= IECLASS_RAWKEY
;
5496 nch
->nch_FakeEvent
.ie_SubClass
= 0;
5497 nSendRawKey(nch
, downevent
? iecode
: iecode
|IECODE_UP_PREFIX
);
5503 switch(nha
->nha_MouseAxis
)
5506 nch
->nch_NewMouseRel
= TRUE
;
5507 nch
->nch_MouseDeltaX
+= value
;
5511 nch
->nch_NewMouseRel
= TRUE
;
5512 nch
->nch_MouseDeltaY
+= value
;
5516 if(nch
->nch_MouseRangeY
)
5518 nch
->nch_NewMouseAbs
= TRUE
;
5520 nch
->nch_MouseAbsX
= value
- nhi
->nhi_RealMin
;
5521 nch
->nch_MouseRangeX
= (nhi
->nhi_RealMax
- nhi
->nhi_RealMin
) + 1;
5525 if(nch
->nch_MouseRangeX
)
5527 nch
->nch_NewMouseAbs
= TRUE
;
5529 nch
->nch_MouseAbsY
= value
- nhi
->nhi_RealMin
;
5530 nch
->nch_MouseRangeY
= (nhi
->nhi_RealMax
- nhi
->nhi_RealMin
) + 1;
5536 qualmask
= 1<<nha
->nha_Qualifier
;
5537 switch(nha
->nha_QualMode
)
5540 nch
->nch_KeyQualifiers
|= qualmask
;
5544 nch
->nch_KeyQualifiers
&= ~qualmask
;
5548 nch
->nch_KeyQualifiers
^= qualmask
;
5552 nch
->nch_KeyQualifiers
&= ~qualmask
;
5555 nch
->nch_KeyQualifiers
|= qualmask
;
5563 UWORD iecode
= IECODE_NOBUTTON
;
5565 BOOL newmouse
= FALSE
;
5567 switch(nha
->nha_ButtonNo
)
5570 iequal
= IEQUALIFIER_LEFTBUTTON
;
5571 iecode
= IECODE_LBUTTON
;
5575 iequal
= IEQUALIFIER_RBUTTON
;
5576 iecode
= IECODE_RBUTTON
;
5580 iequal
= IEQUALIFIER_MIDBUTTON
;
5581 iecode
= IECODE_MBUTTON
;
5585 iecode
= RAWKEY_NM_BUTTON_FOURTH
;
5590 switch(nha
->nha_ButtonMode
)
5593 if((!newmouse
) && (nch
->nch_KeyQualifiers
& iequal
))
5596 iecode
= IECODE_NOBUTTON
;
5598 nch
->nch_KeyQualifiers
|= iequal
;
5599 nch
->nch_MouseButtons
|= 1<<(nha
->nha_ButtonNo
-1);
5604 if(newmouse
|| (nch
->nch_KeyQualifiers
& iequal
))
5606 nch
->nch_KeyQualifiers
&= ~iequal
;
5607 nch
->nch_MouseButtons
&= ~(1<<(nha
->nha_ButtonNo
-1));
5609 iecode
|= IECODE_UP_PREFIX
;
5612 iecode
= IECODE_NOBUTTON
;
5619 if(nch
->nch_MouseButtons
& (1<<(nha
->nha_ButtonNo
-1)))
5621 nch
->nch_MouseButtons
&= ~(1<<(nha
->nha_ButtonNo
-1));
5622 iecode
|= IECODE_UP_PREFIX
;
5624 nch
->nch_MouseButtons
|= 1<<(nha
->nha_ButtonNo
-1);
5627 if(nch
->nch_KeyQualifiers
& iequal
)
5629 nch
->nch_KeyQualifiers
&= ~iequal
;
5630 nch
->nch_MouseButtons
&= ~(1<<(nha
->nha_ButtonNo
-1));
5632 iecode
|= IECODE_UP_PREFIX
;
5634 nch
->nch_KeyQualifiers
|= iequal
;
5635 nch
->nch_MouseButtons
|= 1<<(nha
->nha_ButtonNo
-1);
5643 if((!newmouse
) && (nch
->nch_KeyQualifiers
& iequal
))
5646 iecode
= IECODE_NOBUTTON
;
5648 nch
->nch_KeyQualifiers
|= iequal
;
5649 nch
->nch_MouseButtons
|= 1<<(nha
->nha_ButtonNo
-1);
5652 if(newmouse
|| (nch
->nch_KeyQualifiers
& iequal
))
5654 nch
->nch_KeyQualifiers
&= ~iequal
;
5655 nch
->nch_MouseButtons
&= ~(1<<(nha
->nha_ButtonNo
-1));
5657 iecode
|= IECODE_UP_PREFIX
;
5660 iecode
= IECODE_NOBUTTON
;
5666 iecode
= IECODE_NOBUTTON
;
5669 if(iecode
!= IECODE_NOBUTTON
)
5673 nSendRawKey(nch
, iecode
);
5675 nch
->nch_FakeEvent
.ie_Class
= IECLASS_NEWMOUSE
;
5676 nch
->nch_FakeEvent
.ie_SubClass
= 0;
5677 nch
->nch_FakeEvent
.ie_Code
= iecode
;
5678 nch
->nch_FakeEvent
.ie_NextEvent
= NULL
;
5679 nch
->nch_FakeEvent
.ie_Qualifier
= nch
->nch_KeyQualifiers
;
5680 nch
->nch_InpIOReq
->io_Data
= &nch
->nch_FakeEvent
;
5681 nch
->nch_InpIOReq
->io_Length
= sizeof(struct InputEvent
);
5682 nch
->nch_InpIOReq
->io_Command
= IND_WRITEEVENT
;
5683 DoIO((struct IORequest
*) nch
->nch_InpIOReq
);
5685 nch
->nch_FakeEvent
.ie_X
= nch
->nch_MouseDeltaX
;
5686 nch
->nch_FakeEvent
.ie_Y
= nch
->nch_MouseDeltaY
;
5687 nch
->nch_FakeEvent
.ie_Class
= IECLASS_RAWMOUSE
;
5688 nch
->nch_FakeEvent
.ie_SubClass
= 0;
5689 nch
->nch_FakeEvent
.ie_Code
= iecode
;
5690 nch
->nch_FakeEvent
.ie_NextEvent
= NULL
;
5691 nch
->nch_FakeEvent
.ie_Qualifier
= nch
->nch_KeyQualifiers
|IEQUALIFIER_RELATIVEMOUSE
;
5692 nch
->nch_InpIOReq
->io_Data
= &nch
->nch_FakeEvent
;
5693 nch
->nch_InpIOReq
->io_Length
= sizeof(struct InputEvent
);
5694 nch
->nch_InpIOReq
->io_Command
= nch
->nch_OS4Hack
? IND_ADDEVENT
: IND_WRITEEVENT
;
5695 DoIO((struct IORequest
*) nch
->nch_InpIOReq
);
5696 nch
->nch_NewMouseRel
= FALSE
;
5697 nch
->nch_MouseDeltaX
= 0;
5698 nch
->nch_MouseDeltaY
= 0;
5706 KPRINTF(1, ("Tablet!\n"));
5707 switch(nha
->nha_TabletAxis
)
5710 nch
->nch_MouseAbsZ
= value
- nhi
->nhi_RealMin
;
5711 nch
->nch_MouseRangeZ
= (nhi
->nhi_RealMax
- nhi
->nhi_RealMin
) + 1;
5715 if(nhi
->nhi_RealMax
)
5717 nch
->nch_TabPressure
= ((0x1fffffff / nhi
->nhi_RealMax
)*value
)<<2;
5718 nch
->nch_VldPressure
= TRUE
;
5723 if(nhi
->nhi_RealMax
)
5725 nch
->nch_TabRotX
= ((0x3fffffff / nhi
->nhi_RealMax
)*value
)<<2;
5726 nch
->nch_VldRotX
= TRUE
;
5731 if(nhi
->nhi_RealMax
)
5733 nch
->nch_TabRotY
= ((0x3fffffff / nhi
->nhi_RealMax
)*value
)<<2;
5734 nch
->nch_VldRotY
= TRUE
;
5739 if(nhi
->nhi_RealMax
)
5741 nch
->nch_TabRotZ
= ((0x3fffffff / nhi
->nhi_RealMax
)*value
)<<2;
5742 nch
->nch_VldRotZ
= TRUE
;
5747 nch
->nch_TabProx
= value
;
5748 nch
->nch_VldProx
= TRUE
;
5751 if(nch
->nch_MouseRangeX
&& nch
->nch_MouseRangeY
)
5753 nch
->nch_NewMouseAbs
= TRUE
;
5760 UWORD wheeldist
= 0;
5761 UWORD wheeliecode
= IECODE_NOBUTTON
;
5762 switch(nha
->nha_WheelMode
)
5767 wheeliecode
= RAWKEY_NM_WHEEL_LEFT
;
5772 wheeliecode
= RAWKEY_NM_WHEEL_RIGHT
;
5780 wheeliecode
= RAWKEY_NM_WHEEL_UP
;
5785 wheeliecode
= RAWKEY_NM_WHEEL_DOWN
;
5791 wheeliecode
= RAWKEY_NM_WHEEL_LEFT
;
5792 wheeldist
= nha
->nha_WheelDist
;
5796 wheeliecode
= RAWKEY_NM_WHEEL_RIGHT
;
5797 wheeldist
= nha
->nha_WheelDist
;
5801 wheeliecode
= RAWKEY_NM_WHEEL_UP
;
5802 wheeldist
= nha
->nha_WheelDist
;
5806 wheeliecode
= RAWKEY_NM_WHEEL_DOWN
;
5807 wheeldist
= nha
->nha_WheelDist
;
5810 if(wheeliecode
!= IECODE_NOBUTTON
)
5816 KPRINTF(1, ("Doing wheel %ld\n", wheeliecode
));
5817 nSendRawKey(nch
, wheeliecode
);
5819 nch
->nch_FakeEvent
.ie_Class
= IECLASS_NEWMOUSE
;
5820 nch
->nch_FakeEvent
.ie_SubClass
= 0;
5821 nch
->nch_FakeEvent
.ie_Code
= wheeliecode
;
5822 nch
->nch_FakeEvent
.ie_NextEvent
= NULL
;
5823 nch
->nch_FakeEvent
.ie_Qualifier
= nch
->nch_KeyQualifiers
;
5824 nch
->nch_InpIOReq
->io_Data
= &nch
->nch_FakeEvent
;
5825 nch
->nch_InpIOReq
->io_Length
= sizeof(struct InputEvent
);
5826 nch
->nch_InpIOReq
->io_Command
= IND_WRITEEVENT
;
5827 DoIO((struct IORequest
*) nch
->nch_InpIOReq
);
5831 nSendRawKey(nch
, wheeliecode
|IECODE_UP_PREFIX
);
5833 nch
->nch_FakeEvent
.ie_Class
= IECLASS_NEWMOUSE
;
5834 nch
->nch_FakeEvent
.ie_SubClass
= 0;
5835 nch
->nch_FakeEvent
.ie_Code
= wheeliecode
|IECODE_UP_PREFIX
;
5836 nch
->nch_FakeEvent
.ie_NextEvent
= NULL
;
5837 nch
->nch_FakeEvent
.ie_Qualifier
= nch
->nch_KeyQualifiers
;
5838 nch
->nch_InpIOReq
->io_Data
= &nch
->nch_FakeEvent
;
5839 nch
->nch_InpIOReq
->io_Length
= sizeof(struct InputEvent
);
5840 nch
->nch_InpIOReq
->io_Command
= IND_WRITEEVENT
;
5841 DoIO((struct IORequest
*) nch
->nch_InpIOReq
);
5852 ULONG
*stateptr
= &nch
->nch_LLPortState
[nha
->nha_JoypadPort
];
5854 switch(nha
->nha_JoypadFeat
)
5857 mask
= JPF_JOY_LEFT
;
5861 mask
= JPF_JOY_RIGHT
;
5869 mask
= JPF_JOY_DOWN
;
5873 mask
= JPF_BUTTON_RED
;
5877 mask
= JPF_BUTTON_BLUE
;
5881 mask
= JPF_BUTTON_GREEN
;
5885 mask
= JPF_BUTTON_YELLOW
;
5889 mask
= JPF_BUTTON_FORWARD
;
5893 mask
= JPF_BUTTON_REVERSE
;
5897 mask
= JPF_BUTTON_PLAY
;
5900 case HUAT_HATSWITCH
:
5901 mask
= JP_DIRECTION_MASK
;
5902 stateptr
= &nch
->nch_LLHatswitch
[nha
->nha_JoypadPort
];
5906 /* oldval = *stateptr; */
5907 switch(nha
->nha_JoypadOp
)
5922 if(nha
->nha_JoypadFeat
== HUAT_HATSWITCH
)
5924 value
-= nhi
->nhi_RealMin
;
5925 if((value
>= 0) && (value
< 8))
5927 mask
= LLHatswitchEncoding
[value
];
5931 /*oldval = *stateptr;
5932 oldval &= ~JP_DIRECTION_MASK;
5934 *stateptr = oldval;*/
5951 ULONG
*stateptr
= &nch
->nch_LLAnalogue
[nha
->nha_JoypadPort
];
5952 if((nhi
->nhi_RealMin
!= 0) || (nhi
->nhi_RealMax
!= 255))
5955 value
-= nhi
->nhi_RealMin
;
5957 value
/= (nhi
->nhi_RealMax
- nhi
->nhi_RealMin
);
5959 switch(nha
->nha_APadFeat
)
5962 *stateptr
= (*stateptr
& ~JP_XAXIS_MASK
) | (value
& JP_XAXIS_MASK
) | JP_TYPE_ANALOGUE
;
5966 *stateptr
= (*stateptr
& ~JP_YAXIS_MASK
) | ((value
<<8) & JP_YAXIS_MASK
) | JP_TYPE_ANALOGUE
;
5975 struct NepHidItem
*nhi
;
5977 nhi
= nFindItemID(nch
, nha
->nha_OutItem
, REPORT_MAIN_OUTPUT
, &pos
);
5980 if(nhi
->nhi_Flags
& RPF_MAIN_VARIABLE
)
5982 switch(nha
->nha_OutOp
)
5985 nhi
->nhi_OldValue
= TRUE
;
5989 nhi
->nhi_OldValue
= FALSE
;
5993 nhi
->nhi_OldValue
= nhi
->nhi_OldValue
? FALSE
: TRUE
;
5997 nhi
->nhi_OldValue
= value
;
6001 nParseArrayString(nch
, nhi
, nha
->nha_OutArray
);
6003 nhi
->nhi_Collection
->nhc_Report
->nhr_OutTouched
= TRUE
;
6004 nch
->nch_OutFeatTouched
= TRUE
;
6012 struct NepHidItem
*nhi
;
6014 nhi
= nFindItemID(nch
, nha
->nha_FeatItem
, REPORT_MAIN_FEATURE
, &pos
);
6017 if(nhi
->nhi_Flags
& RPF_MAIN_VARIABLE
)
6019 switch(nha
->nha_FeatOp
)
6022 nhi
->nhi_OldValue
= TRUE
;
6026 nhi
->nhi_OldValue
= FALSE
;
6030 nhi
->nhi_OldValue
= nhi
->nhi_OldValue
? FALSE
: TRUE
;
6034 nhi
->nhi_OldValue
= value
;
6038 nParseArrayString(nch
, nhi
, nha
->nha_OutArray
);
6040 nhi
->nhi_Collection
->nhc_Report
->nhr_FeatTouched
= TRUE
;
6041 nch
->nch_OutFeatTouched
= TRUE
;
6047 nch
->nch_FakeEvent
.ie_Class
= IECLASS_NULL
;
6048 nch
->nch_FakeEvent
.ie_SubClass
= 0;
6049 nch
->nch_FakeEvent
.ie_Code
= IECODE_NOBUTTON
;
6050 nch
->nch_FakeEvent
.ie_NextEvent
= NULL
;
6051 nch
->nch_FakeEvent
.ie_Qualifier
= nch
->nch_KeyQualifiers
;
6052 nch
->nch_InpIOReq
->io_Data
= &nch
->nch_FakeEvent
;
6053 nch
->nch_InpIOReq
->io_Length
= sizeof(struct InputEvent
);
6054 nch
->nch_InpIOReq
->io_Command
= IND_WRITEEVENT
;
6055 switch(nha
->nha_MiscMode
)
6057 case HUAT_DISPLAYBEEP
:
6058 case HUAT_WIN2FRONT
:
6060 case HUAT_ZIPWINDOW
:
6061 case HUAT_SCREENCYCLE
:
6063 case HUAT_ACTWINDOW
:
6065 struct ActionMsg
*am
;
6066 if(!nch
->nch_ClsBase
->nh_DTaskMsgPort
)
6068 nInstallLastActionHero(nch
);
6070 if(nch
->nch_ClsBase
->nh_DTaskMsgPort
)
6072 if((am
= AllocVec(sizeof(struct ActionMsg
), MEMF_PUBLIC
)))
6074 am
->am_Msg
.mn_Length
= sizeof(struct ActionMsg
);
6075 am
->am_Msg
.mn_ReplyPort
= NULL
;
6077 am
->am_Action
= nha
;
6078 PutMsg(nch
->nch_ClsBase
->nh_DTaskMsgPort
, &am
->am_Msg
);
6084 case HUAT_CLOSEWINDOW
:
6085 nch
->nch_FakeEvent
.ie_Class
= IECLASS_CLOSEWINDOW
;
6086 DoIO((struct IORequest
*) nch
->nch_InpIOReq
);
6090 nch
->nch_CDC
->cdc_EnableKBReset
= TRUE
;
6091 nch
->nch_KeyQualifiers
|= IEQUALIFIER_CONTROL
|IEQUALIFIER_LCOMMAND
|IEQUALIFIER_RCOMMAND
;
6095 case HUAT_FLUSHEVENTS
:
6106 LONG
*tarvarptr
= NULL
;
6108 switch(nha
->nha_TarVar
)
6110 case HUAT_LOCALVAR1
:
6111 case HUAT_LOCALVAR2
:
6112 case HUAT_LOCALVAR3
:
6113 case HUAT_LOCALVAR4
:
6114 case HUAT_LOCALVAR5
:
6115 case HUAT_LOCALVAR6
:
6116 case HUAT_LOCALVAR7
:
6117 case HUAT_LOCALVAR8
:
6118 tarvarptr
= &nch
->nch_LocalVars
[nha
->nha_TarVar
- HUAT_LOCALVAR1
];
6129 tarvarptr
= &nch
->nch_ClsBase
->nh_GlobalVars
[nha
->nha_TarVar
- HUAT_GLOBVARA
];
6136 switch(nha
->nha_TarVarOp
)
6143 *tarvarptr
+= value
;
6147 *tarvarptr
-= value
;
6151 *tarvarptr
*= value
;
6157 *tarvarptr
/= value
;
6169 *tarvarptr
= *tarvarptr
&& value
;
6173 *tarvarptr
= !(*tarvarptr
&& value
);
6177 *tarvarptr
= *tarvarptr
&& (!value
);
6181 *tarvarptr
= *tarvarptr
|| value
;
6185 *tarvarptr
= (*tarvarptr
^ value
) ? TRUE
: FALSE
;
6189 *tarvarptr
&= value
;
6193 *tarvarptr
= ~(*tarvarptr
& value
);
6197 *tarvarptr
&= ~value
;
6201 *tarvarptr
|= value
;
6205 *tarvarptr
^= value
;
6209 *tarvarptr
<<= value
;
6213 *tarvarptr
>>= value
;
6220 #if 0 // FIXME looks like AROS does not support this (yet?)
6221 nch
->nch_FakeEvent
.ie_Class
= IECLASS_EXTRAWKEY
;
6222 nch
->nch_FakeEvent
.ie_SubClass
= 0;
6223 nch
->nch_FakeEvent
.ie_Code
= nha
->nha_RawKey
;
6224 // using ie.dead.ie_prev1DownCode instead of ie_extkey.ie_extkey1
6225 nch
->nch_FakeEvent
.ie_position
.ie_dead
.ie_prev1DownCode
= 0xe0;
6226 nch
->nch_FakeEvent
.ie_position
.ie_dead
.ie_prev1DownQual
= nha
->nha_RawKey
;
6227 nch
->nch_FakeEvent
.ie_NextEvent
= NULL
;
6228 nch
->nch_FakeEvent
.ie_Qualifier
= nch
->nch_KeyQualifiers
;
6229 nch
->nch_InpIOReq
->io_Data
= &nch
->nch_FakeEvent
;
6230 nch
->nch_InpIOReq
->io_Length
= sizeof(struct InputEvent
);
6231 nch
->nch_InpIOReq
->io_Command
= IND_WRITEEVENT
;
6232 DoIO((struct IORequest
*) nch
->nch_InpIOReq
);
6241 /* /// "nFlushEvents()" */
6242 void nFlushEvents(struct NepClassHid
*nch
)
6248 struct NepHidReport
*nhr
;
6250 /* output/feature pipes */
6251 if(nch
->nch_OutFeatTouched
)
6253 nch
->nch_OutFeatTouched
= FALSE
;
6254 pp
= nch
->nch_EP0Pipe
;
6255 nhr
= (struct NepHidReport
*) nch
->nch_HidReports
.lh_Head
;
6256 while(nhr
->nhr_Node
.ln_Succ
)
6258 if(nhr
->nhr_OutTouched
)
6260 KPRINTF(1, ("Out Report %ld touched...\n", nhr
->nhr_ReportID
));
6261 buflen
= (nhr
->nhr_ReportOutSize
+7)>>3;
6262 if(nch
->nch_UsesReportID
)
6264 *nch
->nch_EPOutBuf
= nhr
->nhr_ReportID
;
6265 nGenerateOutReport(nch
, nhr
, nch
->nch_EPOutBuf
+1);
6267 psdPipeSetup(pp
, URTF_OUT
|URTF_CLASS
|URTF_INTERFACE
,
6268 UHR_SET_REPORT
, (ULONG
) nhr
->nhr_ReportID
|0x0200, nch
->nch_IfNum
);
6270 nGenerateOutReport(nch
, nhr
, nch
->nch_EPOutBuf
);
6271 psdPipeSetup(pp
, URTF_OUT
|URTF_CLASS
|URTF_INTERFACE
,
6272 UHR_SET_REPORT
, 0x0200, nch
->nch_IfNum
);
6274 KPRINTF(1, ("Len: %ld [%02lx %02lx]", buflen
, nch
->nch_EPOutBuf
[0], nch
->nch_EPOutBuf
[1]));
6275 /*psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname),
6276 "HID OUT Report %02lx Debug (%ld bytes):", nhr->nhr_ReportID, buflen);
6277 nDebugMem(nch, nch->nch_EPOutBuf, buflen);*/
6279 if((ioerr
= psdDoPipe(pp
, nch
->nch_EPOutBuf
, buflen
)))
6281 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
6282 "SET_REPORT(%lx, %ld) failed: %s (%ld)!",
6283 nhr
->nhr_ReportID
|0x0200, buflen
,
6284 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
6286 nhr
->nhr_OutTouched
= FALSE
;
6288 if(nhr
->nhr_FeatTouched
)
6290 KPRINTF(1, ("Feat Report %ld touched...\n", nhr
->nhr_ReportID
));
6291 buflen
= (nhr
->nhr_ReportFeatSize
+7)>>3;
6292 if(nch
->nch_UsesReportID
)
6294 *nch
->nch_EPOutBuf
= nhr
->nhr_ReportID
;
6295 nGenerateFeatReport(nch
, nhr
, nch
->nch_EPOutBuf
+1);
6297 psdPipeSetup(pp
, URTF_OUT
|URTF_CLASS
|URTF_INTERFACE
,
6298 UHR_SET_REPORT
, (ULONG
) nhr
->nhr_ReportID
|0x0300, nch
->nch_IfNum
);
6300 nGenerateFeatReport(nch
, nhr
, nch
->nch_EPOutBuf
);
6301 psdPipeSetup(pp
, URTF_OUT
|URTF_CLASS
|URTF_INTERFACE
,
6302 UHR_SET_REPORT
, 0x0300, nch
->nch_IfNum
);
6304 KPRINTF(1, ("Len: %ld [%02lx %02lx]", buflen
, nch
->nch_EPOutBuf
[0], nch
->nch_EPOutBuf
[1]));
6305 if((ioerr
= psdDoPipe(pp
, nch
->nch_EPOutBuf
, buflen
)))
6307 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
6308 "SET_REPORT(%lx, %ld) failed: %s (%ld)!",
6309 nhr
->nhr_ReportID
|0x0300, buflen
,
6310 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
6312 psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
6313 "SET_REPORT(%lx, %ld)=%02lx%02lx okay!",
6314 nhr->nhr_ReportID|0x0300, buflen,
6315 nch->nch_EPOutBuf[1], nch->nch_EPOutBuf[2]);
6317 nhr
->nhr_FeatTouched
= FALSE
;
6319 nhr
= (struct NepHidReport
*) nhr
->nhr_Node
.ln_Succ
;
6322 if(nch
->nch_NewMouseRel
&& (nch
->nch_MouseDeltaX
|| nch
->nch_MouseDeltaY
))
6324 KPRINTF(1, ("Mouse rel movement...\n"));
6325 nch
->nch_FakeEvent
.ie_X
= nch
->nch_MouseDeltaX
;
6326 nch
->nch_FakeEvent
.ie_Y
= nch
->nch_MouseDeltaY
;
6327 nch
->nch_FakeEvent
.ie_Class
= IECLASS_RAWMOUSE
;
6328 nch
->nch_FakeEvent
.ie_SubClass
= 0;
6329 nch
->nch_FakeEvent
.ie_Code
= IECODE_NOBUTTON
;
6330 nch
->nch_FakeEvent
.ie_NextEvent
= NULL
;
6331 nch
->nch_FakeEvent
.ie_Qualifier
= nch
->nch_KeyQualifiers
|IEQUALIFIER_RELATIVEMOUSE
;
6332 nch
->nch_InpIOReq
->io_Data
= &nch
->nch_FakeEvent
;
6333 nch
->nch_InpIOReq
->io_Length
= sizeof(struct InputEvent
);
6334 nch
->nch_InpIOReq
->io_Command
= nch
->nch_OS4Hack
? IND_ADDEVENT
: IND_WRITEEVENT
;
6335 DoIO((struct IORequest
*) nch
->nch_InpIOReq
);
6336 nch
->nch_NewMouseRel
= FALSE
;
6337 nch
->nch_MouseDeltaX
= 0;
6338 nch
->nch_MouseDeltaY
= 0;
6340 if(nch
->nch_NewMouseAbs
)
6342 ULONG
*tagptr
= nch
->nch_TabTags
;
6343 KPRINTF(1, ("Mouse abs movement...\n"));
6344 nch
->nch_FakeEvent
.ie_EventAddress
= &nch
->nch_TabletEvent
;
6345 nch
->nch_TabletEvent
.ient_RangeX
= nch
->nch_MouseRangeX
;
6346 nch
->nch_TabletEvent
.ient_RangeY
= nch
->nch_MouseRangeY
;
6347 nch
->nch_TabletEvent
.ient_TabletX
= nch
->nch_MouseAbsX
;
6348 nch
->nch_TabletEvent
.ient_TabletY
= nch
->nch_MouseAbsY
;
6349 nch
->nch_TabletEvent
.ient_TagList
= (struct TagItem
*) tagptr
;
6350 if(nch
->nch_MouseRangeZ
)
6352 KPRINTF(1, ("AbsZ %ld\n", nch
->nch_MouseAbsZ
));
6353 *tagptr
++ = TABLETA_TabletZ
;
6354 *tagptr
++ = nch
->nch_MouseAbsZ
;
6355 *tagptr
++ = TABLETA_RangeZ
;
6356 *tagptr
++ = nch
->nch_MouseRangeZ
;
6358 if(nch
->nch_VldRotX
)
6360 KPRINTF(1, ("AngleX %ld\n", nch
->nch_TabRotX
));
6361 *tagptr
++ = TABLETA_AngleX
;
6362 *tagptr
++ = nch
->nch_TabRotX
;
6364 if(nch
->nch_VldRotY
)
6366 KPRINTF(1, ("AngleY %ld\n", nch
->nch_TabRotY
));
6367 *tagptr
++ = TABLETA_AngleY
;
6368 *tagptr
++ = nch
->nch_TabRotY
;
6370 if(nch
->nch_VldRotZ
)
6372 KPRINTF(1, ("AngleZ %ld\n", nch
->nch_TabRotZ
));
6373 *tagptr
++ = TABLETA_AngleZ
;
6374 *tagptr
++ = nch
->nch_TabRotZ
;
6376 if(nch
->nch_VldPressure
)
6378 KPRINTF(1, ("Pressure %ld\n", nch
->nch_TabPressure
));
6379 *tagptr
++ = TABLETA_Pressure
;
6380 *tagptr
++ = nch
->nch_TabPressure
;
6382 *tagptr
++ = TABLETA_ButtonBits
;
6383 *tagptr
++ = nch
->nch_MouseButtons
;
6384 if(nch
->nch_VldProx
)
6386 KPRINTF(1, ("InProx %ld\n", nch
->nch_TabProx
));
6387 *tagptr
++ = TABLETA_InProximity
;
6388 *tagptr
++ = nch
->nch_TabProx
;
6391 nch
->nch_FakeEvent
.ie_Class
= IECLASS_NEWPOINTERPOS
;
6392 nch
->nch_FakeEvent
.ie_SubClass
= IESUBCLASS_NEWTABLET
;
6393 nch
->nch_FakeEvent
.ie_Code
= IECODE_NOBUTTON
;
6394 nch
->nch_FakeEvent
.ie_NextEvent
= NULL
;
6395 nch
->nch_FakeEvent
.ie_Qualifier
= nch
->nch_KeyQualifiers
;
6396 nch
->nch_InpIOReq
->io_Data
= &nch
->nch_FakeEvent
;
6397 nch
->nch_InpIOReq
->io_Length
= sizeof(struct InputEvent
);
6398 nch
->nch_InpIOReq
->io_Command
= IND_WRITEEVENT
;
6399 DoIO((struct IORequest
*) nch
->nch_InpIOReq
);
6400 nch
->nch_NewMouseAbs
= FALSE
;
6406 /* /// "nSendRawKey()" */
6407 void nSendRawKey(struct NepClassHid
*nch
, UWORD key
)
6409 nch
->nch_FakeEvent
.ie_Class
= IECLASS_RAWKEY
;
6410 nch
->nch_FakeEvent
.ie_SubClass
= 0;
6411 nch
->nch_FakeEvent
.ie_Code
= key
;
6412 nch
->nch_FakeEvent
.ie_NextEvent
= NULL
;
6413 nch
->nch_FakeEvent
.ie_Qualifier
= nch
->nch_KeyQualifiers
;
6414 nch
->nch_InpIOReq
->io_Data
= &nch
->nch_FakeEvent
;
6415 nch
->nch_InpIOReq
->io_Length
= sizeof(struct InputEvent
);
6416 nch
->nch_InpIOReq
->io_Command
= nch
->nch_OS4Hack
? IND_ADDEVENT
: IND_WRITEEVENT
;
6417 DoIO((struct IORequest
*) nch
->nch_InpIOReq
);
6421 /* /// "nCheckReset()" */
6422 void nCheckReset(struct NepClassHid
*nch
)
6424 if(nch
->nch_CDC
->cdc_EnableKBReset
&&
6425 (nch
->nch_KeyQualifiers
& (IEQUALIFIER_CONTROL
|IEQUALIFIER_LCOMMAND
|IEQUALIFIER_RCOMMAND
)) ==
6426 (IEQUALIFIER_CONTROL
|IEQUALIFIER_LCOMMAND
|IEQUALIFIER_RCOMMAND
))
6429 struct IOStdReq
*ioreq
;
6430 struct Interrupt tempint
;
6432 struct List
*listhead
= NULL
;
6433 BOOL haskbh
= FALSE
;
6434 KPRINTF(20, ("Reboot!\n"));
6436 if(nch
->nch_CDC
->cdc_EnableRH
)
6438 if((mp
= CreateMsgPort()))
6440 if((ioreq
= (struct IOStdReq
*) CreateIORequest(mp
, sizeof(struct IOStdReq
))))
6442 if(!OpenDevice("keyboard.device", 0, (struct IORequest
*) ioreq
, 0))
6444 /* Find list header of reset handlers */
6445 tempint
.is_Node
.ln_Pred
= NULL
;
6446 tempint
.is_Node
.ln_Succ
= NULL
;
6447 tempint
.is_Node
.ln_Type
= NT_INTERRUPT
;
6448 tempint
.is_Node
.ln_Pri
= 32;
6449 tempint
.is_Node
.ln_Name
= "";
6450 tempint
.is_Code
= NULL
;
6451 ioreq
->io_Command
= KBD_ADDRESETHANDLER
;
6452 ioreq
->io_Data
= &tempint
;
6454 DoIO((struct IORequest
*) ioreq
);
6455 if((node
= tempint
.is_Node
.ln_Pred
))
6457 while(node
->ln_Pred
)
6459 node
= node
->ln_Pred
;
6461 listhead
= (struct List
*) node
;
6463 ioreq
->io_Command
= KBD_REMRESETHANDLER
;
6464 DoIO((struct IORequest
*) ioreq
);
6468 node
= listhead
->lh_Head
;
6469 while(node
->ln_Succ
)
6471 KPRINTF(20, ("Kicking %s\n", node
->ln_Name
));
6472 Cause((struct Interrupt
*) node
);
6474 node
= node
->ln_Succ
;
6476 KPRINTF(20, ("Done... awaiting doom\n"));
6479 psdDelayMS(nch
->nch_CDC
->cdc_ResetDelay
*1000);
6482 KPRINTF(20, ("Reset handler list not found!\n"));
6484 CloseDevice((struct IORequest
*) ioreq
);
6486 DeleteIORequest((struct IORequest
*) ioreq
);
6493 else if(nch
->nch_CDC
->cdc_EnableKBReset
&&
6494 (nch
->nch_KeyQualifiers
& IEQUALIFIER_CONTROL
) &&
6495 (nch
->nch_KeyQualifiers
& (IEQUALIFIER_LALT
|IEQUALIFIER_RALT
)) &&
6496 nch
->nch_FakeEvent
.ie_Code
== RAWKEY_DELETE
)
6498 KPRINTF(20, ("Reboot!\n"));
6499 ShutdownA(SD_ACTION_COLDREBOOT
);
6504 /* /// "nLoadItem()" */
6505 BOOL
nLoadItem(struct NepClassHid
*nch
, struct PsdIFFContext
*rppic
, struct List
*lst
, UWORD idbase
)
6507 struct PsdIFFContext
*itpic
;
6508 struct PsdIFFContext
*actpic
;
6509 struct NepHidAction
*nha
;
6512 struct NepHidActionChunk
*nhac
;
6515 psdSafeRawDoFmt((STRPTR
) buf
, 8, "I%03lx", GET_WTYPE(lst
) - idbase
+ 1);
6516 newform
[0] = AROS_LONG2BE(ID_FORM
);
6517 newform
[1] = AROS_LONG2BE(4);
6519 itpic
= psdFindCfgForm(rppic
, AROS_LONG2BE(newform
[2]));
6524 actpic
= psdFindCfgForm(itpic
, MAKE_ID('A','C','T','N'));
6527 if((nhac
= psdGetCfgChunk(actpic
, MAKE_ID('A','C','D','F'))))
6529 if((nha
= nAllocAction(nch
, lst
, 0)))
6531 CopyMem(&nhac
->nhac_Type
, &nha
->nha_Type
, min(AROS_LONG2BE(nhac
->nhac_Length
), sizeof(struct NepHidActionChunk
) - 8));
6532 if((tmpstr
= psdGetStringChunk(actpic
, MAKE_ID('S','N','D','F'))))
6534 strncpy(nha
->nha_SoundFile
, tmpstr
, 255);
6537 if((tmpstr
= psdGetStringChunk(actpic
, MAKE_ID('V','A','N','S'))))
6539 strncpy(nha
->nha_VanillaString
, tmpstr
, 79);
6542 if((tmpstr
= psdGetStringChunk(actpic
, MAKE_ID('K','E','Y','S'))))
6544 strncpy(nha
->nha_KeyString
, tmpstr
, 79);
6547 if((tmpstr
= psdGetStringChunk(actpic
, MAKE_ID('E','X','E','S'))))
6549 strncpy(nha
->nha_ExeString
, tmpstr
, 79);
6552 if((tmpstr
= psdGetStringChunk(actpic
, MAKE_ID('O','A','R','R'))))
6554 strncpy(nha
->nha_OutArray
, tmpstr
, 255);
6560 actpic
= psdNextCfgForm(actpic
);
6566 /* /// "nSaveItem()" */
6567 struct PsdIFFContext
* nSaveItem(struct NepClassHid
*nch
, struct PsdIFFContext
*rppic
, struct List
*lst
, UWORD idbase
)
6569 struct PsdIFFContext
*itpic
;
6570 struct PsdIFFContext
*actpic
;
6571 struct NepHidAction
*nha
;
6574 struct NepHidActionChunk nhac
;
6575 BOOL isdefault
= TRUE
;
6577 if(!lst
->lh_Head
->ln_Succ
)
6581 nha
= (struct NepHidAction
*) lst
->lh_Head
;
6582 while(nha
->nha_Node
.ln_Succ
)
6584 if(!nha
->nha_IsDefault
)
6588 nha
= (struct NepHidAction
*) nha
->nha_Node
.ln_Succ
;
6594 psdSafeRawDoFmt((STRPTR
) buf
, 8, "I%03lx", GET_WTYPE(lst
) - idbase
+ 1);
6595 newform
[0] = AROS_LONG2BE(ID_FORM
);
6596 newform
[1] = AROS_LONG2BE(4);
6598 itpic
= psdFindCfgForm(rppic
, AROS_LONG2BE(newform
[2]));
6601 itpic
= psdAddCfgEntry(rppic
, newform
);
6607 nhac
.nhac_ID
= AROS_LONG2BE(MAKE_ID('A','C','D','F'));
6608 nhac
.nhac_Length
= AROS_LONG2BE(sizeof(struct NepHidActionChunk
)-8);
6609 nha
= (struct NepHidAction
*) lst
->lh_Head
;
6610 while(nha
->nha_Node
.ln_Succ
)
6612 if(!nha
->nha_IsDefault
)
6616 newform
[2] = AROS_LONG2BE(MAKE_ID('A','C','T','N'));
6617 actpic
= psdAddCfgEntry(itpic
, newform
);
6622 CopyMem(&nha
->nha_Type
, &nhac
.nhac_Type
, sizeof(struct NepHidActionChunk
)-8);
6623 psdAddCfgEntry(actpic
, &nhac
);
6624 if(*nha
->nha_SoundFile
)
6626 psdAddStringChunk(actpic
, MAKE_ID('S','N','D','F'), nha
->nha_SoundFile
);
6628 if(*nha
->nha_VanillaString
)
6630 psdAddStringChunk(actpic
, MAKE_ID('V','A','N','S'), nha
->nha_VanillaString
);
6632 if(*nha
->nha_KeyString
)
6634 psdAddStringChunk(actpic
, MAKE_ID('K','E','Y','S'), nha
->nha_KeyString
);
6636 if(*nha
->nha_ExeString
)
6638 psdAddStringChunk(actpic
, MAKE_ID('E','X','E','S'), nha
->nha_ExeString
);
6640 if(*nha
->nha_OutArray
)
6642 psdAddStringChunk(actpic
, MAKE_ID('O','A','R','R'), nha
->nha_OutArray
);
6644 nha
= (struct NepHidAction
*) nha
->nha_Node
.ln_Succ
;
6650 /* /// "nReadJoyPort()" */
6651 AROS_LH1(ULONG
, nReadJoyPort
,
6652 AROS_LHA(ULONG
, port
, D0
),
6653 struct Library
*, LowLevelBase
, 5, hid
)
6657 struct NepHidBase
*nh
;
6658 struct NepClassHid
*nch
;
6659 ULONG result
= JP_TYPE_NOTAVAIL
;
6662 if(!(nh
= (struct NepHidBase
*) FindName(&SysBase
->LibList
, GM_UNIQUENAME(libname
))))
6667 result
= AROS_CALL1(ULONG
, nh
->nh_LLOldReadJoyPort
,
6668 AROS_LCA(ULONG
, port
, D0
),
6669 struct Library
*, nh
->nh_LowLevelBase
);
6671 KPRINTF(40, ("Before %08lx\n", result
));
6675 nch
= (struct NepClassHid
*) nh
->nh_Interfaces
.lh_Head
;
6676 while(nch
->nch_Node
.ln_Succ
)
6678 mode
= nch
->nch_CDC
->cdc_LLPortMode
[port
];
6679 if(nh
->nh_LLAnalogueOverride
[port
] && nch
->nch_LLAnalogue
[port
])
6686 // case 0: /* don't touch */
6689 case 1: /* overwrite with USB */
6690 result
= nch
->nch_LLPortState
[port
] | nch
->nch_LLHatswitch
[port
] | JP_TYPE_GAMECTLR
;
6693 case 2: /* merge with USB */
6694 if(((result
& JP_TYPE_MASK
) == JP_TYPE_GAMECTLR
) ||
6695 ((result
& JP_TYPE_MASK
) == JP_TYPE_JOYSTK
) ||
6696 ((result
& JP_TYPE_MASK
) == JP_TYPE_UNKNOWN
) ||
6699 result
= (result
& (JP_BUTTON_MASK
|JP_DIRECTION_MASK
)) | nch
->nch_LLPortState
[port
] | nch
->nch_LLHatswitch
[port
] | JP_TYPE_GAMECTLR
;
6703 case 3: /* disable */
6704 result
= JP_TYPE_NOTAVAIL
;
6707 case 4: /* overwrite with analogue USB */
6708 if(nch
->nch_LLAnalogue
[port
])
6710 result
= (nch
->nch_LLPortState
[port
] & ~JP_DIRECTION_MASK
) | (nch
->nch_LLAnalogue
[port
] & JP_XYAXIS_MASK
) | nch
->nch_LLHatswitch
[port
] | JP_TYPE_ANALOGUE
;
6714 nch
= (struct NepClassHid
*) nch
->nch_Node
.ln_Succ
;
6718 if((port
>= JP_ANALOGUE_PORT_MAGIC
) && (port
< (JP_ANALOGUE_PORT_MAGIC
|4)))
6722 nch
= (struct NepClassHid
*) nh
->nh_Interfaces
.lh_Head
;
6723 while(nch
->nch_Node
.ln_Succ
)
6725 if(nch
->nch_LLAnalogue
[port
])
6727 result
= (nch
->nch_LLPortState
[port
] & ~JP_DIRECTION_MASK
) | (nch
->nch_LLAnalogue
[port
] & JP_XYAXIS_MASK
) | nch
->nch_LLHatswitch
[port
] | JP_TYPE_ANALOGUE
;
6729 nch
= (struct NepClassHid
*) nch
->nch_Node
.ln_Succ
;
6733 KPRINTF(40, ("And after %08lx\n", result
));
6740 /* /// "nSetJoyPortAttrsA()" */
6741 AROS_LH2(ULONG
, nSetJoyPortAttrsA
,
6742 AROS_LHA(ULONG
, port
, D0
),
6743 AROS_LHA(struct TagItem
*, tags
, A1
),
6744 struct Library
*, LowLevelBase
, 22, hid
)
6748 struct NepHidBase
*nh
;
6749 struct TagItem
*typetag
;
6750 struct TagItem
*motortags
[2];
6751 struct TagItem
*motorofftag
;
6752 ULONG result
= FALSE
;
6754 if(!(nh
= (struct NepHidBase
*) FindName(&SysBase
->LibList
, GM_UNIQUENAME(libname
))))
6759 result
= AROS_CALL2(ULONG
, nh
->nh_LLOldSetJoyPortAttrsA
,
6760 AROS_LCA(ULONG
, port
, D0
),
6761 AROS_LCA(struct TagItem
*, tags
, A1
),
6762 struct Library
*, nh
->nh_LowLevelBase
);
6764 KPRINTF(40, ("Before %08lx\n", result
));
6767 typetag
= FindTagItem(SJA_Type
, tags
);
6770 if(typetag
->ti_Data
== SJA_TYPE_ANALOGUE
)
6772 nh
->nh_LLAnalogueOverride
[port
] = TRUE
;
6774 nh
->nh_LLAnalogueOverride
[port
] = FALSE
;
6778 typetag
= FindTagItem(SJA_Reinitialize
, tags
);
6781 if(typetag
->ti_Data
)
6783 nh
->nh_LLAnalogueOverride
[port
] = FALSE
;
6786 motortags
[0] = FindTagItem(SJA_RumbleSetSlowMotor
, tags
);
6787 motortags
[1] = FindTagItem(SJA_RumbleSetFastMotor
, tags
);
6788 motorofftag
= FindTagItem(SJA_RumbleOff
, tags
);
6789 if(motortags
[0] || motortags
[1] || motorofftag
)
6791 struct NepHidItem
*nhi
;
6792 struct NepClassHid
*nch
;
6793 struct TagItem nulltag
= { 0, 0 };
6798 if(motorofftag
->ti_Data
)
6800 motortags
[0] = &nulltag
;
6801 motortags
[1] = &nulltag
;
6805 nch
= (struct NepClassHid
*) nh
->nh_Interfaces
.lh_Head
;
6806 while(nch
->nch_Node
.ln_Succ
)
6808 if(nch
->nch_CDC
->cdc_LLRumblePort
== port
+1)
6810 for(cnt
= 0; cnt
< 2; cnt
++)
6812 if(motortags
[cnt
] && ((nhi
= nch
->nch_RumbleMotors
[cnt
])))
6814 if(nhi
->nhi_OldValue
!= motortags
[cnt
]->ti_Data
)
6816 nhi
->nhi_OldValue
= motortags
[cnt
]->ti_Data
;
6817 nhi
->nhi_Collection
->nhc_Report
->nhr_OutTouched
= TRUE
;
6818 nch
->nch_OutFeatTouched
= TRUE
;
6825 Signal(nch
->nch_Task
, (1L<<nch
->nch_TaskMsgPort
->mp_SigBit
));
6829 nch
= (struct NepClassHid
*) nch
->nch_Node
.ln_Succ
;
6835 KPRINTF(40, ("And after %08lx\n", result
));
6843 /* /// "nInstallLastActionHero()" */
6844 void nInstallLastActionHero(struct NepClassHid
*nch
)
6846 struct NepHidBase
*nh
= nch
->nch_ClsBase
;
6848 if(!nh
->nh_DispatcherTask
)
6850 nh
->nh_ReadySignal
= SIGB_SINGLE
;
6851 nh
->nh_ReadySigTask
= FindTask(NULL
);
6852 SetSignal(0, SIGF_SINGLE
);
6853 if(psdSpawnSubTask("Last Action Hero", GM_UNIQUENAME(nDispatcherTask
), nh
))
6855 Wait(1L<<nh
->nh_ReadySignal
);
6856 if(!nh
->nh_DispatcherTask
)
6858 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
),
6859 "It's your fault! I'm sure! Couldn't create subtask for launching!");
6861 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
6862 "Last Action Hero successfully launched!");
6865 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
),
6866 "It's your fault! I'm sure! Couldn't create subtask for launching!");
6868 nh
->nh_ReadySigTask
= NULL
;
6869 //FreeSignal(nh->nh_ReadySignal);
6874 /************************************************************************/
6878 /* /// "nDispatcherTask()" */
6879 AROS_UFH0(void, GM_UNIQUENAME(nDispatcherTask
))
6883 struct NepHidBase
*nh
;
6884 struct Task
*thistask
;
6885 struct ActionMsg
*am
;
6886 struct NepHidSound
*nhs
;
6888 thistask
= FindTask(NULL
);
6891 #undef IntuitionBase
6893 #undef DataTypesBase
6894 nh
= thistask
->tc_UserData
;
6895 NewList(&nh
->nh_Sounds
);
6896 if((nh
->nh_InpMsgPort
= CreateMsgPort()))
6898 if((nh
->nh_InpIOReq
= (struct IOStdReq
*) CreateIORequest(nh
->nh_InpMsgPort
, sizeof(struct IOStdReq
))))
6900 if(!OpenDevice("input.device", 0, (struct IORequest
*) nh
->nh_InpIOReq
, 0))
6902 if((nh
->nh_DOSBase
= OpenLibrary("dos.library", 39)))
6904 if((nh
->nh_IntBase
= (struct IntuitionBase
*) OpenLibrary("intuition.library", 39)))
6906 #define IntuitionBase nh->nh_IntBase
6907 if((nh
->nh_DTBase
= OpenLibrary("datatypes.library", 39)))
6909 if((nh
->nh_CxBase
= OpenLibrary("commodities.library", 39)))
6911 if((nh
->nh_LayersBase
= OpenLibrary("layers.library", 39)))
6913 #define CxBase nh->nh_CxBase
6914 #define DOSBase nh->nh_DOSBase
6915 #define DataTypesBase nh->nh_DTBase
6916 #define LayersBase nh->nh_LayersBase
6917 if((nh
->nh_DTaskMsgPort
= CreateMsgPort()))
6919 nh
->nh_DispatcherTask
= thistask
;
6921 if(nh
->nh_ReadySigTask
)
6923 Signal(nh
->nh_ReadySigTask
, 1L<<nh
->nh_ReadySignal
);
6927 nLastActionHero(nh
);
6930 while((am
= (struct ActionMsg
*) GetMsg(nh
->nh_DTaskMsgPort
)))
6934 nhs
= (struct NepHidSound
*) nh
->nh_Sounds
.lh_Head
;
6935 while(nhs
->nhs_Node
.ln_Succ
)
6937 nFreeSound(nh
, nhs
);
6938 nhs
= (struct NepHidSound
*) nh
->nh_Sounds
.lh_Head
;
6940 DeleteMsgPort(nh
->nh_DTaskMsgPort
);
6941 nh
->nh_DTaskMsgPort
= NULL
;
6944 CloseLibrary(nh
->nh_LayersBase
);
6945 nh
->nh_LayersBase
= NULL
;
6947 CloseLibrary(nh
->nh_CxBase
);
6948 nh
->nh_CxBase
= NULL
;
6950 CloseLibrary(nh
->nh_DTBase
);
6951 nh
->nh_DTBase
= NULL
;
6953 CloseLibrary((struct Library
*) nh
->nh_IntBase
);
6954 nh
->nh_IntBase
= NULL
;
6956 CloseLibrary((struct Library
*) nh
->nh_DOSBase
);
6957 nh
->nh_DOSBase
= NULL
;
6959 CloseDevice((struct IORequest
*) nh
->nh_InpIOReq
);
6961 DeleteIORequest((struct IORequest
*) nh
->nh_InpIOReq
);
6962 nh
->nh_InpIOReq
= NULL
;
6964 DeleteMsgPort(nh
->nh_InpMsgPort
);
6965 nh
->nh_InpMsgPort
= NULL
;
6968 if(nh
->nh_ReadySigTask
)
6970 Signal(nh
->nh_ReadySigTask
, 1L<<nh
->nh_ReadySignal
);
6972 nh
->nh_DispatcherTask
= NULL
;
6978 /* /// "nLastActionHero()" */
6979 void nLastActionHero(struct NepHidBase
*nh
)
6983 struct ActionMsg
*am
;
6984 struct NepHidAction
*nha
;
6985 struct NepClassHid
*nch
;
6986 struct Window
*actwindow
;
6987 struct Screen
*actscreen
;
6990 sigmask
= (1L<<nh
->nh_DTaskMsgPort
->mp_SigBit
)|SIGBREAKF_CTRL_C
;
6993 while((am
= (struct ActionMsg
*) GetMsg(nh
->nh_DTaskMsgPort
)))
6996 nha
= am
->am_Action
;
6997 switch(nha
->nha_Type
& HUA_ATYPEMASK
)
7001 strcpy(&buf
[1], nha
->nha_VanillaString
);
7003 if(!nSendKeyString(nh
, buf
))
7005 nEasyRequest(nh
, "'%s' is no good. Really.", "Argl!", nha
->nha_VanillaString
);
7010 if(!nSendKeyString(nh
, nha
->nha_KeyString
))
7012 nEasyRequest(nh
, "Don't you ever say\n'%s'\nto me again!", "Terribly sorry!", nha
->nha_KeyString
);
7017 nPlaySound(nh
, nha
);
7024 if((fhandle
= Open(nch
->nch_CDC
->cdc_ShellCon
, MODE_READWRITE
)))
7026 ioerr
= SystemTags(nha
->nha_ExeString
,
7029 SYS_Asynch
, nha
->nha_ShellAsync
,
7030 NP_StackSize
, nch
->nch_CDC
->cdc_ShellStack
,
7034 nEasyRequest(nh
, "Offender survived execution of\n'%s'\nwith error code %ld.", "Get me a shotgun then!", nha
->nha_ExeString
, ioerr
);
7036 if((!nha
->nha_ShellAsync
) || ioerr
)
7041 nEasyRequest(nh
, "Do you really think\n'%s'\nis a nice and witty\nconsole window? Well, it's not!", "I'll use that string to hang myself!", nch
->nch_CDC
->cdc_ShellCon
);
7047 switch(nha
->nha_MiscMode
)
7049 case HUAT_ACTWINDOW
:
7051 struct Layer
*toplayer
;
7052 intlock
= LockIBase(0);
7053 actscreen
= nh
->nh_IntBase
->ActiveScreen
;
7054 actwindow
= nh
->nh_IntBase
->ActiveWindow
;
7055 UnlockIBase(intlock
);
7058 LockLayerInfo(&actscreen
->LayerInfo
);
7059 toplayer
= WhichLayer(&actscreen
->LayerInfo
, (LONG
) actscreen
->MouseX
, (LONG
) actscreen
->MouseY
);
7060 UnlockLayerInfo(&actscreen
->LayerInfo
);
7064 if(toplayer
->Window
&& (actwindow
!= toplayer
->Window
))
7066 ActivateWindow(toplayer
->Window
);
7073 case HUAT_DISPLAYBEEP
:
7081 case HUAT_SCREENCYCLE
:
7082 intlock
= LockIBase(0);
7083 actscreen
= nh
->nh_IntBase
->FirstScreen
;
7084 UnlockIBase(intlock
);
7087 ScreenToBack(actscreen
);
7091 case HUAT_WIN2FRONT
:
7092 intlock
= LockIBase(0);
7093 actwindow
= nh
->nh_IntBase
->ActiveWindow
;
7094 UnlockIBase(intlock
);
7097 WindowToFront(actwindow
);
7102 intlock
= LockIBase(0);
7103 actwindow
= nh
->nh_IntBase
->ActiveWindow
;
7104 UnlockIBase(intlock
);
7107 WindowToBack(actwindow
);
7111 case HUAT_ZIPWINDOW
:
7112 intlock
= LockIBase(0);
7113 actwindow
= nh
->nh_IntBase
->ActiveWindow
;
7114 UnlockIBase(intlock
);
7117 ZipWindow(actwindow
);
7127 sigs
= Wait(sigmask
);
7128 } while(!(sigs
& SIGBREAKF_CTRL_C
));
7132 /* /// "nLoadSound()" */
7133 struct NepHidSound
* nLoadSound(struct NepHidBase
*nh
, STRPTR name
)
7135 struct NepHidSound
*nhs
;
7136 if((nhs
= AllocVec(sizeof(struct NepHidSound
), MEMF_PUBLIC
|MEMF_CLEAR
)))
7138 if((nhs
->nhs_Node
.ln_Name
= AllocVec((ULONG
) strlen(name
)+1, MEMF_PUBLIC
)))
7140 strcpy(nhs
->nhs_Node
.ln_Name
, name
);
7141 AddTail(&nh
->nh_Sounds
, &nhs
->nhs_Node
);
7142 nhs
->nhs_DTHandle
= NewDTObject(name
,
7143 DTA_SourceType
, DTST_FILE
,
7144 DTA_GroupID
, GID_SOUND
,
7147 if(!nhs
->nhs_DTHandle
)
7149 nEasyRequest(nh
, "Does '%s' make a sound\nin the woods, when it was chopped\nbut nobody was looking at it?", "No! Couldn't load it!", name
);
7159 /* /// "nPlaySound()" */
7160 BOOL
nPlaySound(struct NepHidBase
*nh
, struct NepHidAction
*nha
)
7162 struct NepHidSound
*nhs
;
7163 struct dtTrigger playmsg
;
7164 nhs
= (struct NepHidSound
*) FindName(&nh
->nh_Sounds
, nha
->nha_SoundFile
);
7167 nhs
= nLoadSound(nh
, nha
->nha_SoundFile
);
7173 if(!nhs
->nhs_DTHandle
)
7178 SetAttrs(nhs
->nhs_DTHandle
,
7179 SDTA_Volume
, nha
->nha_SoundVolume
,
7181 playmsg
.MethodID
= DTM_TRIGGER
;
7182 playmsg
.dtt_GInfo
= NULL
;
7183 playmsg
.dtt_Function
= STM_PLAY
;
7184 playmsg
.dtt_Data
= NULL
;
7185 DoMethodA(nhs
->nhs_DTHandle
, (Msg
) &playmsg
);
7190 /* /// "nFreeSound()" */
7191 void nFreeSound(struct NepHidBase
*nh
, struct NepHidSound
*nhs
)
7193 Remove(&nhs
->nhs_Node
);
7194 if(nhs
->nhs_DTHandle
)
7196 DisposeDTObject(nhs
->nhs_DTHandle
);
7198 FreeVec(nhs
->nhs_Node
.ln_Name
);
7203 /* /// "nInvertString()" */
7204 struct InputEvent
*nInvertString(struct NepHidBase
*nh
, STRPTR str
, struct KeyMap
*km
)
7206 struct InputEvent
*prior
= NULL
;
7207 struct InputEvent
*ne
;
7208 struct InputXpression tmpIX
;
7210 BOOL freeevents
= FALSE
;
7214 if(!str
) return(NULL
);
7215 if(!(*str
)) return(NULL
);
7218 if((ne
= AllocMem(sizeof(struct InputEvent
), MEMF_CLEAR
)))
7220 ne
->ie_NextEvent
= prior
;
7225 case '<': /* do angles */
7233 if(!ParseIX(oldsptr
, &tmpIX
))
7236 prior
->ie_Class
= tmpIX
.ix_Class
;
7237 prior
->ie_Code
= tmpIX
.ix_Code
;
7238 prior
->ie_Qualifier
= tmpIX
.ix_Qualifier
;
7247 case '\\': /* do escape sequences */
7270 if(freeevents
) break;
7271 /* note that this break is missing on purpose */
7272 default: /* normal key translation */
7273 InvertKeyMap((ULONG
) cc
, prior
, km
);
7279 } while(*str
&& (!freeevents
));
7282 nFreeIEvents(nh
, prior
);
7289 /* /// "nFreeIEvents()" */
7290 void nFreeIEvents(struct NepHidBase
*nh
, struct InputEvent
*event
)
7292 struct InputEvent
*next
;
7295 next
= event
->ie_NextEvent
;
7296 FreeMem(event
, sizeof(struct InputEvent
));
7302 /* /// "nSendKeyString()" */
7303 BOOL
nSendKeyString(struct NepHidBase
*nh
, STRPTR str
)
7305 struct InputEvent
*events
= nInvertString(nh
, str
, NULL
);
7306 struct InputEvent
*eptr
= events
;
7307 struct InputEvent lastevent
;
7317 eptr
= eptr
->ie_NextEvent
;
7322 for(lstpos
= --count
; lstpos
; lstpos
--)
7323 eptr
= eptr
->ie_NextEvent
;
7325 nh
->nh_FakeEvent
= *eptr
;
7326 nh
->nh_FakeEvent
.ie_NextEvent
= NULL
;
7327 nh
->nh_InpIOReq
->io_Data
= &nh
->nh_FakeEvent
;
7328 nh
->nh_InpIOReq
->io_Length
= sizeof(struct InputEvent
);
7329 nh
->nh_InpIOReq
->io_Command
= nh
->nh_OS4Hack
? IND_ADDEVENT
: IND_WRITEEVENT
;
7330 DoIO((struct IORequest
*) nh
->nh_InpIOReq
);
7332 nh
->nh_FakeEvent
.ie_Code
|= IECODE_UP_PREFIX
;
7333 nh
->nh_InpIOReq
->io_Data
= &nh
->nh_FakeEvent
;
7334 nh
->nh_InpIOReq
->io_Length
= sizeof(struct InputEvent
);
7335 nh
->nh_InpIOReq
->io_Command
= nh
->nh_OS4Hack
? IND_ADDEVENT
: IND_WRITEEVENT
;
7336 DoIO((struct IORequest
*) nh
->nh_InpIOReq
);
7338 lastevent
.ie_Class
= IECLASS_RAWKEY
;
7339 lastevent
.ie_SubClass
= 0;
7340 lastevent
.ie_Code
= 0xFF;
7341 lastevent
.ie_NextEvent
= NULL
;
7342 lastevent
.ie_Qualifier
= 0;
7343 nh
->nh_InpIOReq
->io_Data
= &lastevent
;
7344 nh
->nh_InpIOReq
->io_Length
= sizeof(struct InputEvent
);
7345 nh
->nh_InpIOReq
->io_Command
= nh
->nh_OS4Hack
? IND_ADDEVENT
: IND_WRITEEVENT
;
7346 DoIO((struct IORequest
*) nh
->nh_InpIOReq
);
7347 nFreeIEvents(nh
, events
);
7352 /* /// "nEasyRequest()" */
7353 LONG
nEasyRequest(struct NepHidBase
*nh
, STRPTR body
, STRPTR gadgets
, ...)
7357 AROS_SLOWSTACKFORMAT_PRE(gadgets
);
7358 ret
= nEasyRequestA(nh
, body
, gadgets
, AROS_SLOWSTACKFORMAT_ARG(gadgets
));
7359 AROS_SLOWSTACKFORMAT_POST(gadgets
);
7365 /* /// "nEasyRequestA()" */
7366 LONG
nEasyRequestA(struct NepHidBase
*nh
, STRPTR body
, STRPTR gadgets
, RAWARG params
)
7368 struct EasyStruct es
;
7369 es
.es_StructSize
= sizeof(struct EasyStruct
);
7371 es
.es_Title
= GM_UNIQUENAME(libname
);
7372 es
.es_TextFormat
= body
;
7373 es
.es_GadgetFormat
= gadgets
;
7374 return(EasyRequestArgs(NULL
, &es
, NULL
, params
));