That's my weekend work about WiiMote's
Hope some one found that interesting
First some .decls
file wii_kernel32.decls
file wii_hid.decls
file wii_setupapi.decls
and finally, one .bb: Wimote1.bb
Hope some one found that interesting
First some .decls
file wii_kernel32.decls
.lib "Kernel32.dll" wiiCreateFile%(lpFileName$, dwDesiredAccess, dwShareMode, lpSecurrityAttributes, dwCreationDistribution, dwFlagsAndAttributes, hTemplateFile) : "CreateFileA" wiiCreateFileOverlapped%(lpFileName$, dwDesiredAccess, dwShareMode, lpSecurrityAttributes*, dwCreationDistribution, dwFlagsAndAttributes, hTemplateFile) : "CreateFileA" wiiCloseHandle%(hObject) : "CloseHandle" wiiWriteFile%(hFile, lpBuffer*, nNumberOfBytesToWrite, lpNumberOfBytesWritten*, lpOverlapped) : "WriteFile" wiiReadFile%(hFile, lpBuffer*, nNumberOfBytesToRead, lpNumberOfBytesRead*, lpOverlapped*) : "ReadFile" wiiWaitForSingleObject%(nHandle, dwMilliseconds) : "WaitForSingleObject" wiiCreateEvent%(lpSecurityAttributes*, bManualReset, bInitialState, lpName ) : "CreateEventA" wiiResetEvent%(hEvent) : "ResetEvent" wiiCancelIo%(hFile) : "CancelIo"
file wii_hid.decls
.lib "Hid.dll" wiiHidD_GetAttributes%(HidDeviceObject, Attributes*): "HidD_GetAttributes" wiiHidD_GetHidGuid%(HidGuid*) : "HidD_GetHidGuid"
file wii_setupapi.decls
.lib "setupapi.dll" wiiSetupDiDestroyDeviceInfoList%(DeviceInfoSet) : "SetupDiDestroyDeviceInfoList" wiiSetupDiEnumDeviceInterfaces%(DeviceInfoSet, DeviceInfoData, InterfaceClassGuid*, MemberIndex, DeviceInterfaceData*) : "SetupDiEnumDeviceInterfaces" wiiSetupDiGetClassDevs%(ClassGuid*, Enumerator$, hwndParent, Flags) : "SetupDiGetClassDevsA" wiiSetupDiGetDeviceInterfaceDetail%(DeviceInfoSet, DeviceInterfaceData*, DeviceInterfaceDetailData, DeviceInterfaceDetailDataSize, RequiredSize*, DeviceInfoData) : "SetupDiGetDeviceInterfaceDetailA" wiiSetupDiGetDeviceInterfaceDetail2%(DeviceInfoSet, DeviceInterfaceData*, DeviceInterfaceDetailData*, DeviceInterfaceDetailDataSize, RequiredSize*, DeviceInfoData) : "SetupDiGetDeviceInterfaceDetailA"
and finally, one .bb: Wimote1.bb
; ; I hope this should be of interest for some one else ; I try to do the things easy, and I ask for help.... ...., wait, wait, .... ; but no one seems to be working with wiimotes in Blitz3d. ; ; so that's my weekend work! ; ; ; If some one need translation, ask me, I do what I can ; (only if i's necesary) ; ; Juan Ignacio Odriozola ; jio@... ;********************************************************************************* ; ; WiiMote desde Blitz3d ; ; .decls necesarios: wii_hid.decls, wii_kernel32.decls, wii_setupapi.decls ; (en las definiciones de las funciones se les ha incorporado wii como prefijo) ; ; ObtenerHID: Busca un WiiMote, si lo encuentra fija HIDHandle para escritura y ; ReadHandle para lectura solapada. Devuelve true o false según exito o no. ; ; Escribir(Cantidad) ;transmite 22 bytes siempre (HIDHandle) ; ;previo hay que inicializar OutputReportData con la info a Tx ; ;Cantidad indica cuantos he inicializado, para que la rutina ; ;borre el resto del buffer ; ; Leer(TOut) ;Ordena una lectura (ReadHandle), espera recibir 22 bytes o TOut ; ;Si operación de lectura exitosa devuelve True, si TOut devuelve False ; ; Si Lectura exitosa: WiiMote\DReporting = Tipo de reporte recibido ; WiiMote\RxCount = cantidad de bytes recibidos ; ReadBuffer contiene los bytes recibidos ; ; ; Si BlueSolei ha detectado alguna vez al WiiMote, es encontrado en la lista por ; ObtenerHID, se le asigna un HIDHandle y un ReadHandle. ; Leer puede dar TimeOut porque el WiiMote se ha apagado, se quedó sin batería etc. ; ; ; ; Uso: Teclas 1, 2, 3, 4 Prenden/Apagan los leds del WiiMote ; Tecla 5 apaga los 4 leds ; Tecla 6: Activa/Desactiva vibración (rumble) ; ; Esc: Fin del programa ; Depurando = true/false: debug on/off ; ; ; ; "Básicamente traduje un programa Visual Basic 6" originalmente escrito por Jean Axelson ; para la comunicación con HID, pensado en forma genérica para cualquier dispositivo USB ; modificado por: para encontrar un WiiMote. ; ; Escribí las .decls desde el .bas de Visual en el que se declaraban las api's para visual. ; ; modifique unas cuantas cosas, tanto que no se parece mucho al original, para que pudieran ; ser usadas desde Blitz3d. ; ; por ahora estoy conforme, espero le sirva a alguien más. ; ; ; Referencias: ; ; Trabajo original de Jean Axelson ; www.Lvr.com/hidpage.htm ; Primera modificación para WiiMote ; 2007/1/9 tokkyo (http://onakasuita.org/wii/) ; see <a href="http://www.wiili.org/index.php/Wiimote" target="_blank">http://www.wiili.org/index.php/Wiimote</a> For details ; ; ; mucha información ; <a href="http://wiibrew.org/index.php?title=Wiimote" target="_blank">http://wiibrew.org/index.php?title=Wiimote</a> <<<<< Gracias mil! ; ; ;********************************************************************************* Const REGISTER_IR = $04b00030 Const REGISTER_IR_SENSITIVITY_1 = $04b00000 Const REGISTER_IR_SENSITIVITY_2 = $04b0001a Const REGISTER_IR_MODE = $04b00033 Const REGISTER_EXTENSION_INIT = $04a40040 Const REGISTER_EXTENSION_TYPE = $04a400fe Const REGISTER_EXTENSION_CALIBRATION = $04a40020 Global HIDHandle Global ReadHandle Global MyDeviceDetected=False Global OutputReportData = CreateBank(255) Global ReadBuffer = CreateBank( 22) Global Security = CreateBank( 12) Global HIDOverlapped = CreateBank( 20) Global EventObject Global Depurando=True Type Controller Field Rumble = False Field TxContinuo = False Field Led1 = False Field Led2 = False Field Led3 = False Field Led4 = False Field IrMode = 0 ;off, basic, extended, full: 00, 01, 03, 05 Field DReporting ;Primer byte de la respuesta Field DRNoConocido Field RxCount Field Energia Field Botones1 ; . . . + Up Dn Rg Lf Field Botones2 ; H . . - A B 1 2 Field Boton_A = False Field Boton_B = False Field Boton_Minus = False Field Boton_Home = False Field Boton_Plus = False Field Boton_One = False Field Boton_Two = False Field Boton_Up = False Field Boton_Down = False Field Boton_Left = False Field Boton_Right = False Field AccelX Field Accely Field AccelZ Field PMx ;coordenadas del punto medio de P1 y P2 (IR) Field PMy Field P1x ;para los 4 puntos IR Field P1y Field P1t ;-1 si no se ve, o si no un campo Presente Field P2x Field P2y Field P2t Field P3x Field P3y Field P3t Field P4x Field P4y Field P4t End Type Global WiiMote.Controller = New Controller SetBuffer BackBuffer() MyDeviceDetected = ObtenerHID() SolicitarEstado() NoIR() ModoDeRespuesta($31) ;continuous = off: solo tx si hay cambios ; Repeat Cls LeoTeclado() If Leer(10) Then EvaluoRecepcion Else ;time out Locate 10,100 Write "TimeOut" End If ;muestro variables del WiiMote ;los últimos valores recibidos Locate 10,10 Write WiiMote\AccelX Locate 40,10 Write WiiMote\AccelY Locate 70,10 Write WiiMote\AccelZ Locate 100,10 Write "Batt: "+WiiMote\Energia Locate 180,10 If WiiMote\Led1 Then Write "1" Else Write "." End If Locate 190,10 If WiiMote\Led2 Then Write "1" Else Write "." End If Locate 200,10 If WiiMote\Led3 Then Write "1" Else Write "." End If Locate 210,10 If WiiMote\Led4 Then Write "1" Else Write "." End If Locate 10,30 Write Right$(Bin$(WiiMote\Botones1),8) + "-" +Right$(Bin$(WiiMote\Botones2),8) Locate 200,30 Write "?: "+WiiMote\DRNoConocido Flip True Until KeyHit(1) FreeBank HIDOverlapped If MyDeviceDetected Then Result = wiiCloseHandle(HIDHandle) Result = wiiCloseHandle(ReadHandle) End If FreeBank Security FreeBank OutputReportData FreeBank ReadBuffer End ;**************************************************************************************** Function LeoTeclado() If KeyHit(2) Then ;tecla 1 WiiMote\Led1 = Not(WiiMote\Led1) ActualizarLeds() End If If KeyHit(3) Then ;tecla 2 WiiMote\Led2 = Not(WiiMote\Led2) ActualizarLeds() End If If KeyHit(4) Then ;tecla 3 WiiMote\Led3 = Not(WiiMote\Led3) ActualizarLeds() End If If KeyHit(5) Then ;tecla 4 WiiMote\Led4 = Not(WiiMote\Led4) ActualizarLeds() End If If KeyHit(6) Then ;tecla 5 apaga todos los leds ;leds apagados, rumble off ControlarLeds(False,False,False,False) Escribir(2) SolicitarEstado() End If If KeyHit(7) Then WiiMote\Rumble = Not(WiiMote\Rumble) ActualizarLeds() End If End Function Function ActualizarLeds() ControlarLeds(WiiMote\Led4,WiiMote\Led3,WiiMote\Led2,WiiMote\Led1) End Function Function ControlarLeds(l1,l2,l3,l4) ;LEDS 0x11 Dato=0 If l1 Then Dato=$80 If l2 Then Dato=Dato Or $40 If l3 Then Dato=Dato Or $20 If l4 Then Dato=Dato Or $10 If WiiMote\Rumble Then Dato=Dato Or $01 PokeByte(OutputReportData,0,$11) PokeByte(OutputReportData,1,Dato) Escribir(2) End Function Function NoIR() ;disable IR PokeByte(OutputReportData,0,$13) PokeByte(OutputReportData,1, 0) Escribir(2) PokeByte(OutputReportData,0,$1A) PokeByte(OutputReportData,1, 0) Escribir(2) WiiMote\P1t = -1 WiiMote\P2t = -1 WiiMote\P3t = -1 WiiMote\P4t = -1 End Function Function ModoDeRespuesta(tipo) ;TYPE 0x12 PokeByte(OutputReportData,0,$12) PokeByte(OutputReportData,1, 0) PokeByte(OutputReportData,2,tipo) Escribir(3) End Function Function SolicitarEstado() ;STATUS 0x15 PokeByte(OutputReportData,0,$15) PokeByte(OutputReportData,1, 0) Escribir(2) ;status End Function ; rutinas que analizan los datos del buffer de lectura ; son invocadas desde EvaluoRecepción, dependiento del tipo de reporte. Function DeglozarBotones() Byte1 = PeekByte(ReadBuffer,1) Byte2 = PeekByte(ReadBuffer,2) WiiMote\Botones1 = Byte1 And $1F ;0001 1111 WiiMote\Botones2 = Byte2 And $9F ;1001 1111 WiiMote\Boton_A = (Byte2 And $08) <> 0 WiiMote\Boton_B = (Byte2 And $04) <> 0 WiiMote\Boton_Minus = (Byte2 And $10) <> 0 WiiMote\Boton_Home = (Byte2 And $80) <> 0 WiiMote\Boton_Plus = (Byte1 And $10) <> 0 WiiMote\Boton_One = (Byte2 And $02) <> 0 WiiMote\Boton_Two = (Byte2 And $01) <> 0 WiiMote\Boton_Up = (Byte1 And $08) <> 0 WiiMote\Boton_Down = (Byte1 And $04) <> 0 WiiMote\Boton_Left = (Byte1 And $01) <> 0 WiiMote\Boton_Right = (Byte1 And $02) <> 0 End Function Function DeglozarAceleraciones() WiiMote\AccelX = PeekByte(ReadBuffer,3) WiiMote\AccelY = PeekByte(ReadBuffer,4) WiiMote\AccelZ = PeekByte(ReadBuffer,5) End Function Function EvaluoRecepcion() ;se llama solo si se ha recibido ok Select WiiMote\DReporting Case $20 ;status WiiMote\Energia = PeekByte(ReadBuffer,6) WiiMote\Led1 = (PeekByte(ReadBuffer,3) And $80) <> 0 WiiMote\Led2 = (PeekByte(ReadBuffer,3) And $40) <> 0 WiiMote\Led3 = (PeekByte(ReadBuffer,3) And $20) <> 0 WiiMote\Led4 = (PeekByte(ReadBuffer,3) And $10) <> 0 WiiMote\TxContinuo = (PeekByte(ReadBuffer,3) And $08) <> 0 Case $21 ;Read Case $22 ;write Case $30 DeglozarBotones() Case $31 DeglozarBotones() DeglozarAceleraciones() Case $32 DeglozarBotones() Case $33 DeglozarBotones() DeglozarAceleraciones() Case $34 DeglozarBotones() Case $35 DeglozarBotones() DeglozarAceleraciones() Case $36 DeglozarBotones() Case $37 DeglozarBotones() DeglozarAceleraciones() Case $3D Case $3E DeglozarBotones() Case $3F DeglozarBotones() Default WiiMote\DRNoConocido = WiiMote\DRNoConocido + 1 End Select End Function ;funciones más que necesarias ;ObtenerHID, Leer, Escribir Function Leer(TOut) ;1) Si dispositivo no detectado, trata de encontrar uno ; ;2) Si dispositivo encotrado, manda leer ; si Lectura completada con éxito: devuelve true => ReadBuffer tiene lo recibido ; si TOut: cancela la lectura y devuelve false LecturaOk = False If MyDeviceDetected = False Then ;intento encontrar uno MyDeviceDetected = ObtenerHID() End If If MyDeviceDetected Then ;si hay uno WAIT_TIMEOUT = $102 WAIT_OBJECT_0 = $0 NBRx = CreateBank(4) ;Inicio la operación de lectura Result = wiiReadFile(ReadHandle, ReadBuffer, 22, NBRx, HIDOverlapped) ;Regresa inmediatamente WiiMote\RxCount = PeekInt(NBRx,0) FreeBank NBRx ;ahora espero a que lleguen los 22 o timeout Result = wiiWaitForSingleObject(EventObject, TOut) ;esto espera mismo. ;ahora hay que evaluar los casos. Select Result Case WAIT_OBJECT_0 ;ReadFile has completed WiiMote\DReporting = PeekByte(ReadBuffer,0) LecturaOk = True Case WAIT_TIMEOUT ;Timeout ;Cancelo la operación Result = wiiCancelIo(ReadHandle) LecturaOk = False Default LecturaOk = False End Select wiiResetEvent(EventObject) End If Return LecturaOk ;true si habia un witmote y rx ok sin time out ;false si habio uno y time out, o no habia y sigue sin haber End Function Function Escribir(Cantidad) ;si dispositivo no detectado, trata de encontrar uno ;si ya hay uno ; previo al llamado hay que ubicar en OutputReportData los datos a transmitir ; Cantidad indica cuantos hay en el buffer ; siempre se transmiten 22 NumeroDeBytesEscritos = 0 If MyDeviceDetected = False Then MyDeviceDetected = ObtenerHID() Else OutBuffer=CreateBank(22) ;copio de OutputReportData a OutBuffer solo Cantidad bytes ;el resto se borra For i=0 To 21 If i<Cantidad Then PokeByte(OutBuffer,i,PeekByte(OutputReportData,i)) Else PokeByte(OutBuffer,i,0) End If Next Temp = CreateBank(4) Result = wiiWriteFile(HIDHandle, OutputReportData, 22, Temp, 0) NumeroDeBytesEscritos = PeekInt(Temp,0) FreeBank Temp FreeBank OutBuffer End If Return NumeroDeBytesEscritos End Function Function ObtenerHID() ;busca en la lista de dispositivos el primer WiiMote ;si lo encuentra, abre dos archivos HIDHandle para escritura ;y ReadHandle para lectura Overlapped ;devuelve MyDeviceDetected que indica si la operación fué exitosa FILE_SHARE_READ = $1 FILE_SHARE_WRITE = $2 GENERIC_READ = $80000000 GENERIC_WRITE = $40000000 OPEN_EXISTING = 3 FILE_FLAG_OVERLAPPED = $40000000 GUID = CreateBank(16) ;long, int, int, array(0..7) byte ;son estructuras, en las que el primer elemento (4 bytes) indica su tamaño ;se pasan por referencia y hay que inicializar su tamaño antes de usarlas MyDeviceInterfaceDetailData = CreateBank(5) PokeInt(MyDeviceInterfaceDetailData,0,5) MyDeviceInfoData = CreateBank(28) PokeInt(MyDeviceInfoData,0,28) MyDeviceInterfaceData = CreateBank(28) PokeInt(MyDeviceInterfaceData,0,28) ;esta estructura es escrita por HidD_GetAttributes, de ella se saca Vendedor, producto y versión DeviceAttributes = CreateBank(10) ;size(4), VendorID, ProductID, Version 2,2,2. DeviceInfoSet=0 DevicePathName$="" Flags = 16 + 2 DetailData=0 LastDevice=False Detectado = False ;Security es una estructura con tres variables tipo long PokeInt(Security, 0, 12) ;length PokeInt(Security, 4, 0) ;lpSecurityDescriptor PokeInt(Security, 8,True) ;bInheritHandle HIDHandle = -1 Result = wiiHidD_GetHidGuid(GUID) If Depurando Then DebugLog t DebugLog Hex(PeekInt(GUID,0)) DebugLog Right$(Hex(PeekShort(GUID,4)),4) DebugLog Right$(Hex(PeekShort(GUID,6)),4) For i=8 To 15 DebugLog Right$(Hex(PeekByte(GUID,i)),2) Next End If DeviceInfoSet = wiiSetupDiGetClassDevs(GUID,"",0,Flags) MemberIndex=0 Needed = CreateBank(4) Repeat ;PokeInt(MyDeviceInterfaceData,0,28) Result = wiiSetupDiEnumDeviceInterfaces(DeviceInfoSet,0,GUID,MemberIndex,MyDeviceInterfaceData) If Result = 0 Then LastDevice = True Else ;PokeInt(MyDeviceInfoData,0,28) ;tercer parámetro por valor Result = wiiSetupDiGetDeviceInterfaceDetail(DeviceInfoSet, MyDeviceInterfaceData, 0, 0, Needed, 0) DetailData = PeekInt(Needed,0) ;PokeInt(MyDeviceInterfaceDetailData,0,5) DetailDataBuffer = CreateBank(DetailData) Cuantos = DetailData PokeInt(DetailDataBuffer,0,5) ;tercer parámetro por referencia Result = wiiSetupDiGetDeviceInterfaceDetail2(DeviceInfoSet, MyDeviceInterfaceData, DetailDataBuffer, DetailData, Needed, 0) strtmp$ = "" For i=4 To Cuantos-1 strtmp$ = strtmp$ + Chr$(PeekByte(DetailDataBuffer,i)) Next DebugLog strtmp$ FreeBank DetailDataBuffer DevicePathName$ = strtmp$ HIDHandle = wiiCreateFileOverlapped(DevicePathName, GENERIC_READ Or GENERIC_WRITE, (FILE_SHARE_READ Or FILE_SHARE_WRITE), Security, OPEN_EXISTING, 0, 0) If Depurando Then DebugLog "Handle ID: "+HIDHandle Result = wiiHidD_GetAttributes(HIDHandle, DeviceAttributes) VendorID = PeekShort(DeviceAttributes,4) ProductID = PeekShort(DeviceAttributes,6) If Depurando Then DebugLog "VendorID : "+Hex(VendorID)+" Product: "+Hex(ProductID) If (VendorID = $057E) And (ProductID = $0306) Then Detectado = True ReadHandle = wiiCreateFileOverlapped(DevicePathName, GENERIC_READ Or GENERIC_WRITE, (FILE_SHARE_READ Or FILE_SHARE_WRITE), Security, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0) ;preparativos para la transferencia solapada If EventObject = 0 Then EventObject = wiiCreateEvent(Security,True,True,"") End If ;HIDOverlapped es una estructura con 5 variables tipo Long ;Internal, InternalHigh, Offset, OffsetHigh, hEvent PokeInt(HIDOverlapped, 8,0) ;offset PokeInt(HIDOverlapped,12,0) ;offsethigh PokeInt(HIDOverlapped,16,EventObject) ;hEvent If Depurando Then DebugLog "WiiMote encontrado" Else Detectado = False If Depurando Then DebugLog "No es el que yo busco" Result = wiiCloseHandle(HIDHandle) End If End If MemberIndex = MemberIndex+1 Until (LastDevice = True) Or (Detectado = True) FreeBank Needed Result = wiiSetupDiDestroyDeviceInfoList(DeviceInfoSet) FreeBank GUID FreeBank MyDeviceInterfaceData FreeBank MyDeviceInterfaceDetailData FreeBank MyDeviceInfoData FreeBank DeviceAttributes Return Detectado End Function