1 /*-------------------------------------------------------------
3 usbkeyboard.c -- Usb keyboard support(boot protocole)
5 Copyright (C) 2008, 2009
6 DAVY Guillaume davyg2@gmail.com
8 This software is provided 'as-is', without any express or implied
9 warranty. In no event will the authors be held liable for any
10 damages arising from the use of this software.
12 Permission is granted to anyone to use this software for any
13 purpose, including commercial applications, and to alter it and
14 redistribute it freely, subject to the following restrictions:
16 1. The origin of this software must not be misrepresented; you
17 must not claim that you wrote the original software. If you use
18 this software in a product, an acknowledgment in the product
19 documentation would be appreciated but is not required.
21 2. Altered source versions must be plainly marked as such, and
22 must not be misrepresented as being the original software.
24 3. This notice may not be removed or altered from any source
27 -------------------------------------------------------------*/
37 #include <wiikeyboard/usbkeyboard.h>
39 #define HEAP_SIZE 4096
43 //Check if two device are equal
44 bool devEqual(device dev1
,device dev2
)
46 return (dev1
.vid
==dev2
.vid
&& dev1
.pid
==dev2
.pid
);
49 //Call when the keyboard is disconnected
50 s32
_disconnect(s32 retval
,void* data
)
52 keyboard
*key
= (keyboard
*) data
;
55 ev
.type
= USBKEYBOARD_DISCONNECTED
;
57 for (i
=0;i
<key
->numCB
;i
++)
58 (*key
->cb
[i
]) (ev
,key
->cbData
[i
]);
63 s32
USBKeyboard_Initialize()
68 hId
= iosCreateHeap(HEAP_SIZE
);
77 s32
USBKeyboard_Deinitialize()
80 retval
= iosDestroyHeap(hId
);
85 //Search all the keyboard connected to the wii usb port
86 //Thanks to Sven Peter usbstorage support
87 s32
USBKeyboard_Find(device (*devs
)[DEVLIST_MAXSIZE
])
94 buffer
= memalign(32, DEVLIST_MAXSIZE
<< 3);
97 memset(buffer
, 0, DEVLIST_MAXSIZE
<< 3);
99 if (USB_GetDeviceList("/dev/usb/oh0", buffer
, DEVLIST_MAXSIZE
, 0, &dummy
) < 0)
106 for(i
= 0; i
< DEVLIST_MAXSIZE
; i
++)
108 memcpy(&vid
, (buffer
+ (i
<< 3) + 4), 2);
109 memcpy(&pid
, (buffer
+ (i
<< 3) + 6), 2);
111 if ((vid
==0)||(pid
==0))
115 if (USB_OpenDevice("oh0",vid
,pid
,&fd
)<0)
118 u32 iConf
, iInterface
;
120 usb_configurationdesc
*ucd
;
121 usb_interfacedesc
*uid
;
122 USB_GetDescriptors(fd
, &udd
);
123 for(iConf
= 0; iConf
< udd
.bNumConfigurations
; iConf
++)
125 ucd
= &udd
.configurations
[iConf
];
126 for(iInterface
= 0; iInterface
< ucd
->bNumInterfaces
; iInterface
++)
128 uid
= &ucd
->interfaces
[iInterface
];
129 if ( (uid
->bInterfaceClass
== USB_CLASS_HID
) && (uid
->bInterfaceSubClass
== USB_SUBCLASS_BOOT
) && (uid
->bInterfaceProtocol
== USB_PROTOCOL_KEYBOARD
))
131 (*devs
)[num
].vid
= vid
;
132 (*devs
)[num
].pid
= pid
;
138 USB_FreeDescriptors(&udd
);
139 USB_CloseDevice(&fd
);
144 //Open a keyboard from his pid and vid that you can have with USBKeyboard_find
145 s32
USBKeyboard_Open(keyboard
*key
,device dev
)
147 if (USB_OpenDevice("oh0",dev
.vid
,dev
.pid
,&key
->fd
)<0)
150 u32 iConf
, iInterface
, iEp
;
152 usb_configurationdesc
*ucd
;
153 usb_interfacedesc
*uid
;
154 usb_endpointdesc
*ued
;
156 //Search a interrupt endPoint thanks to the usb descriptor
157 USB_GetDescriptors(key
->fd
, &udd
);
158 for(iConf
= 0; iConf
< udd
.bNumConfigurations
; iConf
++)
160 ucd
= &udd
.configurations
[iConf
];
161 for(iInterface
= 0; iInterface
< ucd
->bNumInterfaces
; iInterface
++)
163 uid
= &ucd
->interfaces
[iInterface
];
164 if ( (uid
->bInterfaceClass
== USB_CLASS_HID
) && (uid
->bInterfaceSubClass
== USB_SUBCLASS_BOOT
) && (uid
->bInterfaceProtocol
== USB_PROTOCOL_KEYBOARD
))
166 for(iEp
= 0; iEp
< uid
->bNumEndpoints
; iEp
++)
168 ued
= &uid
->endpoints
[iEp
];
169 if (ued
->bmAttributes
!= USB_ENPOINT_INTERRUPT
)
171 if (!(ued
->bEndpointAddress
& USB_ENDPOINT_IN
))
173 key
->ep
= ued
->bEndpointAddress
;
174 key
->ep_size
= ued
->wMaxPacketSize
;
175 key
->configuration
= ucd
->bConfigurationValue
;
176 key
->interface
= uid
->bInterfaceNumber
;
177 key
->altInterface
= uid
->bAlternateSetting
;
183 USB_FreeDescriptors(&udd
);
187 USB_FreeDescriptors(&udd
);
191 if(USB_GetConfiguration(key
->fd
, &conf
) < 0)
193 if(conf
!= key
->configuration
&& USB_SetConfiguration(key
->fd
, key
->configuration
) < 0)
195 if(key
->altInterface
!= 0 && USB_SetAlternativeInterface(key
->fd
, key
->interface
, key
->altInterface
) < 0)
198 if (USBKeyboard_Get_Protocol(key
)!=0)
200 if (USBKeyboard_Set_Protocol(key
, 0)<0)
202 USBKeyboard_Close(key
);
205 if (USBKeyboard_Get_Protocol(key
)==1)
207 USBKeyboard_Close(key
);
216 if (USB_DeviceRemovalNotifyAsync(key
->fd
,&_disconnect
,key
)<0)
218 USBKeyboard_Close(key
);
226 s32
USBKeyboard_Close(keyboard
*key
)
228 return USB_CloseDevice(&(key
->fd
));
231 //Get the protocol, 0=bout protocol and 1=report protocol
232 s32
USBKeyboard_Get_Protocol(keyboard
*key
)
236 buffer
= iosAlloc(hId
, 1);
239 USB_WriteCtrlMsg(key
->fd
,USB_REQTYPE_GET
,USB_REQ_GETPROTOCOL
,0,0,1,buffer
);
241 iosFree(hId
, buffer
);
245 //Modifie the protocol, 0=bout protocol and 1=report protocol
246 s32
USBKeyboard_Set_Protocol(keyboard
*key
, u8 protocol
)
248 return USB_WriteCtrlMsg(key
->fd
,USB_REQTYPE_SET
,USB_REQ_SETPROTOCOL
,protocol
,0,0,0);
251 //Get a input report from interrupt pipe
252 s32
USBKeyboard_Get_InputReport_Intr(keyboard
*key
)
255 buffer
= iosAlloc(hId
, 8);
258 s32 ret
= USB_ReadIntrMsg(key
->fd
,key
->ep
,8,buffer
);
259 memcpy(key
->keyNew
,buffer
,8);
260 iosFree(hId
, buffer
);
264 //Get a input report from control pipe
265 s32
USBKeyboard_Get_OutputReport_Ctrl(keyboard
*key
,u8
*leds
)
268 buffer
= iosAlloc(hId
, 1);
271 s32 ret
= USB_WriteCtrlMsg(key
->fd
,USB_REQTYPE_GET
,USB_REQ_GETREPORT
, USB_REPTYPE_OUTPUT
<<8 | 0,0,1,buffer
);
272 memcpy(leds
,buffer
,1);
273 iosFree(hId
, buffer
);
277 //Set a input report to control pipe
278 s32
USBKeyboard_Set_OutputReport_Ctrl(keyboard
*key
)
281 buffer
= iosAlloc(hId
, 1);
284 memcpy(buffer
,&key
->leds
,1);
285 s32 ret
= USB_WriteCtrlMsg(key
->fd
,USB_REQTYPE_SET
,USB_REQ_SETREPORT
, USB_REPTYPE_OUTPUT
<<8 | 0,0,1,buffer
);
286 iosFree(hId
, buffer
);
290 void USBKeyboard_SubmitEvent(keyboard
*key
, USBKeyboard_eventType type
, u8 code
)
292 USBKeyboard_event ev
;
296 for (i
=0;i
<key
->numCB
;i
++)
297 (*key
->cb
[i
]) (ev
,key
->cbData
[i
]);
300 //Get the pressed touch and call the cb fonction
301 s32
USBKeyboard_GetState(keyboard
*key
)
304 u8 bad_message
[6] = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
305 if (USBKeyboard_Get_InputReport_Intr(key
)<0)
308 if (memcmp(key
->keyNew
+ 2, bad_message
, 6) == 0)
311 if(key
->keyNew
[0] != key
->oldState
) {
312 if ((key
->keyNew
[0] & 0x02) && !(key
->oldState
& 0x02)) {
313 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_PRESSED
, 0xe1);
314 } else if ((key
->oldState
& 0x02) && !(key
->keyNew
[0] & 0x02)) {
315 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_RELEASED
, 0xe1);
318 if ((key
->keyNew
[0] & 0x20) && !(key
->oldState
& 0x20)) {
319 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_PRESSED
, 0xe5);
320 } else if ((key
->oldState
& 0x20) && !(key
->keyNew
[0] & 0x20)) {
321 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_RELEASED
, 0xe5);
324 if ((key
->keyNew
[0] & 0x01) && !(key
->oldState
& 0x01)) {
325 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_PRESSED
, 0xe0);
326 } else if ((key
->oldState
& 0x01) && !(key
->keyNew
[0] & 0x01)) {
327 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_RELEASED
, 0xe0);
330 if ((key
->keyNew
[0] & 0x10) && !(key
->oldState
& 0x10)) {
331 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_PRESSED
, 0xe4);
332 } else if ((key
->oldState
& 0x10) && !(key
->keyNew
[0] & 0x10)) {
333 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_RELEASED
, 0xe4);
336 if ((key
->keyNew
[0] & 0x04) && !(key
->oldState
& 0x04)) {
337 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_PRESSED
, 0xe2);
338 } else if ((key
->oldState
& 0x04) && !(key
->keyNew
[0] & 0x04)) {
339 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_RELEASED
, 0xe2);
342 if ((key
->keyNew
[0] & 0x40) && !(key
->oldState
& 0x40)) {
343 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_PRESSED
, 0xe6);
344 } else if ((key
->oldState
& 0x40) && !(key
->keyNew
[0] & 0x40)) {
345 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_RELEASED
, 0xe6);
348 if ((key
->keyNew
[0] & 0x08) && !(key
->oldState
& 0x08)) {
349 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_PRESSED
, 0xe3);
350 } else if ((key
->oldState
& 0x08) && !(key
->keyNew
[0] & 0x08)) {
351 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_RELEASED
, 0xe3);
354 if ((key
->keyNew
[0] & 0x80) && !(key
->oldState
& 0x80)) {
355 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_PRESSED
, 0xe7);
356 } else if ((key
->oldState
& 0x80) && !(key
->keyNew
[0] & 0x80)) {
357 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_RELEASED
, 0xe7);
360 for (i
= 2; i
< 8; i
++)
362 if (key
->keyOld
[i
] > 3 && memchr(key
->keyNew
+ 2, key
->keyOld
[i
], 6) == NULL
)
364 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_RELEASED
, key
->keyOld
[i
]);
366 if (key
->keyNew
[i
] > 3 && memchr(key
->keyOld
+ 2, key
->keyNew
[i
], 6) == NULL
)
368 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_PRESSED
, key
->keyNew
[i
]);
371 memcpy(key
->keyOld
, key
->keyNew
, 8);
372 key
->oldState
= key
->keyNew
[0];
377 s32
USBKeyboard_PutOnLed(keyboard
*key
,USBKeyboard_led led
)
379 key
->leds
= key
->leds
| (1 << led
);
380 if (USBKeyboard_Set_OutputReport_Ctrl(key
)<0)
385 //Put off the led led
386 s32
USBKeyboard_PutOffLed(keyboard
*key
,USBKeyboard_led led
)
388 key
->leds
= key
->leds
& (255 ^ (1 << led
));
389 if (USBKeyboard_Set_OutputReport_Ctrl(key
)<0)
394 //Switch the led led, put on if off or put off if on
395 s32
USBKeyboard_SwitchLed(keyboard
*key
,USBKeyboard_led led
)
397 key
->leds
= key
->leds
^ (1 << led
);
398 if (USBKeyboard_Set_OutputReport_Ctrl(key
)<0)
403 //Add a callback function who will handlethe keyboard events
404 s32
USBKeyboard_Add_EventCB(keyboard
* key
,eventcallback cb
, void* data
)
406 if (key
->numCB
==CBEVENT_MAXNUM
)
408 key
->cb
[key
->numCB
] = cb
;
409 key
->cbData
[key
->numCB
] = data
;
414 //Add a callback function who will handlethe keyboard events
415 s32
USBKeyboard_Remove_EventCB(keyboard
* key
,u8 n
)
417 if (n
>=CBEVENT_MAXNUM
)
420 for (i
=n
;i
<key
->numCB
-1;i
++)
422 key
->cb
[i
] = key
->cb
[i
+1];
423 key
->cbData
[i
] = key
->cbData
[i
+1];