1 /*-------------------------------------------------------------
3 usbkeyboard.c -- Usb keyboard support(boot protocol)
5 Copyright (C) 2008, 2009
6 DAVY Guillaume davyg2@gmail.com
9 This software is provided 'as-is', without any express or implied
10 warranty. In no event will the authors be held liable for any
11 damages arising from the use of this software.
13 Permission is granted to anyone to use this software for any
14 purpose, including commercial applications, and to alter it and
15 redistribute it freely, subject to the following restrictions:
17 1. The origin of this software must not be misrepresented; you
18 must not claim that you wrote the original software. If you use
19 this software in a product, an acknowledgment in the product
20 documentation would be appreciated but is not required.
22 2. Altered source versions must be plainly marked as such, and
23 must not be misrepresented as being the original software.
25 3. This notice may not be removed or altered from any source
28 -------------------------------------------------------------*/
38 #include <wiikeyboard/usbkeyboard.h>
40 #define HEAP_SIZE 4096
41 #define DEVLIST_MAXSIZE 8
45 //Callback when the keyboard is disconnected
46 static s32
_disconnect(s32 retval
,void* data
)
48 USBKeyboard
*key
= (USBKeyboard
*) data
;
55 ev
.type
= USBKEYBOARD_DISCONNECTED
;
57 key
->cb(ev
,key
->cbData
);
62 static void USBKeyboard_SubmitEvent(USBKeyboard
*key
, USBKeyboard_eventType type
, u8 code
)
71 key
->cb(ev
,key
->cbData
);
75 s32
USBKeyboard_Initialize(void)
80 hId
= iosCreateHeap(HEAP_SIZE
);
89 s32
USBKeyboard_Deinitialize(void)
95 retval
= iosDestroyHeap(hId
);
100 //Search for a keyboard connected to the wii usb port
101 //Thanks to Sven Peter usbstorage support
102 s32
USBKeyboard_Find(u16
*vid
, u16
*pid
)
113 buffer
= memalign(32, DEVLIST_MAXSIZE
<< 3);
116 memset(buffer
, 0, DEVLIST_MAXSIZE
<< 3);
118 if (USB_GetDeviceList("/dev/usb/oh0", buffer
, DEVLIST_MAXSIZE
, 0, &dummy
) < 0)
124 for(i
= 0; i
< DEVLIST_MAXSIZE
; i
++)
126 p_vid
= *((u16
*) (buffer
+ (i
<< 3) + 4));
127 p_pid
= *((u16
*) (buffer
+ (i
<< 3) + 6));
129 if ((p_vid
==0) || (p_pid
==0))
133 if (USB_OpenDevice("oh0", p_vid
, p_pid
, &fd
) < 0)
136 u32 iConf
, iInterface
;
138 usb_configurationdesc
*ucd
;
139 usb_interfacedesc
*uid
;
140 USB_GetDescriptors(fd
, &udd
);
141 for(iConf
= 0; iConf
< udd
.bNumConfigurations
; iConf
++)
143 ucd
= &udd
.configurations
[iConf
];
144 for(iInterface
= 0; iInterface
< ucd
->bNumInterfaces
; iInterface
++)
146 uid
= &ucd
->interfaces
[iInterface
];
147 if ( (uid
->bInterfaceClass
== USB_CLASS_HID
) && (uid
->bInterfaceSubClass
== USB_SUBCLASS_BOOT
) && (uid
->bInterfaceProtocol
== USB_PROTOCOL_KEYBOARD
))
160 USB_FreeDescriptors(&udd
);
161 USB_CloseDevice(&fd
);
172 //Open a keyboard from his pid and vid that you retrieved with USBKeyboard_Find
173 s32
USBKeyboard_Open(USBKeyboard
*key
, u16 vid
, u16 pid
)
178 key
->connect
= false;
180 if (USB_OpenDevice("oh0", vid
,pid
, &key
->fd
) < 0)
183 u32 iConf
, iInterface
, iEp
;
185 usb_configurationdesc
*ucd
;
186 usb_interfacedesc
*uid
;
187 usb_endpointdesc
*ued
;
189 //Search a interrupt endPoint thanks to the usb descriptor
190 USB_GetDescriptors(key
->fd
, &udd
);
191 for(iConf
= 0; iConf
< udd
.bNumConfigurations
; iConf
++)
193 ucd
= &udd
.configurations
[iConf
];
194 for(iInterface
= 0; iInterface
< ucd
->bNumInterfaces
; iInterface
++)
196 uid
= &ucd
->interfaces
[iInterface
];
197 if ( (uid
->bInterfaceClass
== USB_CLASS_HID
) && (uid
->bInterfaceSubClass
== USB_SUBCLASS_BOOT
) && (uid
->bInterfaceProtocol
== USB_PROTOCOL_KEYBOARD
))
199 for(iEp
= 0; iEp
< uid
->bNumEndpoints
; iEp
++)
201 ued
= &uid
->endpoints
[iEp
];
202 if (ued
->bmAttributes
!= USB_ENPOINT_INTERRUPT
)
204 if (!(ued
->bEndpointAddress
& USB_ENDPOINT_IN
))
206 key
->ep
= ued
->bEndpointAddress
;
207 key
->ep_size
= ued
->wMaxPacketSize
;
208 key
->configuration
= ucd
->bConfigurationValue
;
209 key
->interface
= uid
->bInterfaceNumber
;
210 key
->altInterface
= uid
->bAlternateSetting
;
216 USB_FreeDescriptors(&udd
);
220 USB_FreeDescriptors(&udd
);
224 if(USB_GetConfiguration(key
->fd
, &conf
) < 0) {
225 USBKeyboard_Close(key
);
229 if(conf
!= key
->configuration
&& USB_SetConfiguration(key
->fd
, key
->configuration
) < 0) {
230 USBKeyboard_Close(key
);
234 if(key
->altInterface
!= 0 && USB_SetAlternativeInterface(key
->fd
, key
->interface
, key
->altInterface
) < 0) {
235 USBKeyboard_Close(key
);
239 if (USBKeyboard_Get_Protocol(key
)!=0)
241 if (USBKeyboard_Set_Protocol(key
, 0)<0)
243 USBKeyboard_Close(key
);
246 if (USBKeyboard_Get_Protocol(key
)==1)
248 USBKeyboard_Close(key
);
253 if (USB_DeviceRemovalNotifyAsync(key
->fd
,&_disconnect
,key
)<0)
255 USBKeyboard_Close(key
);
268 s32
USBKeyboard_Close(USBKeyboard
*key
)
270 s32 res
= USB_CloseDevice(&(key
->fd
));
271 key
->connect
= false;
276 //Get the protocol, 0=bout protocol and 1=report protocol
277 s32
USBKeyboard_Get_Protocol(USBKeyboard
*key
)
281 buffer
= iosAlloc(hId
, 1);
284 USB_WriteCtrlMsg(key
->fd
,USB_REQTYPE_GET
,USB_REQ_GETPROTOCOL
,0,0,1,buffer
);
286 iosFree(hId
, buffer
);
290 //Modify the protocol, 0=bout protocol and 1=report protocol
291 s32
USBKeyboard_Set_Protocol(USBKeyboard
*key
, u8 protocol
)
293 return USB_WriteCtrlMsg(key
->fd
,USB_REQTYPE_SET
,USB_REQ_SETPROTOCOL
,protocol
,0,0,0);
296 //Get an input report from interrupt pipe
297 s32
USBKeyboard_Get_InputReport_Intr(USBKeyboard
*key
)
300 buffer
= iosAlloc(hId
, 8);
303 s32 ret
= USB_ReadIntrMsg(key
->fd
,key
->ep
,8,buffer
);
304 memcpy(key
->keyNew
,buffer
,8);
305 iosFree(hId
, buffer
);
309 //Get an input report from control pipe
310 s32
USBKeyboard_Get_OutputReport_Ctrl(USBKeyboard
*key
,u8
*leds
)
313 buffer
= iosAlloc(hId
, 1);
316 s32 ret
= USB_WriteCtrlMsg(key
->fd
,USB_REQTYPE_GET
,USB_REQ_GETREPORT
, USB_REPTYPE_OUTPUT
<<8 | 0,0,1,buffer
);
317 memcpy(leds
,buffer
,1);
318 iosFree(hId
, buffer
);
322 //Set an input report to control pipe
323 s32
USBKeyboard_Set_OutputReport_Ctrl(USBKeyboard
*key
)
326 buffer
= iosAlloc(hId
, 1);
329 memcpy(buffer
,&key
->leds
,1);
330 s32 ret
= USB_WriteCtrlMsg(key
->fd
,USB_REQTYPE_SET
,USB_REQ_SETREPORT
, USB_REPTYPE_OUTPUT
<<8 | 0,0,1,buffer
);
331 iosFree(hId
, buffer
);
335 //Scan for key presses and generate events for the callback function
336 s32
USBKeyboard_Scan(USBKeyboard
*key
)
339 u8 bad_message
[6] = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
340 if (USBKeyboard_Get_InputReport_Intr(key
)<0)
343 if (memcmp(key
->keyNew
+ 2, bad_message
, 6) == 0)
346 if(key
->keyNew
[0] != key
->oldState
) {
347 if ((key
->keyNew
[0] & 0x02) && !(key
->oldState
& 0x02)) {
348 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_PRESSED
, 0xe1);
349 } else if ((key
->oldState
& 0x02) && !(key
->keyNew
[0] & 0x02)) {
350 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_RELEASED
, 0xe1);
353 if ((key
->keyNew
[0] & 0x20) && !(key
->oldState
& 0x20)) {
354 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_PRESSED
, 0xe5);
355 } else if ((key
->oldState
& 0x20) && !(key
->keyNew
[0] & 0x20)) {
356 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_RELEASED
, 0xe5);
359 if ((key
->keyNew
[0] & 0x01) && !(key
->oldState
& 0x01)) {
360 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_PRESSED
, 0xe0);
361 } else if ((key
->oldState
& 0x01) && !(key
->keyNew
[0] & 0x01)) {
362 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_RELEASED
, 0xe0);
365 if ((key
->keyNew
[0] & 0x10) && !(key
->oldState
& 0x10)) {
366 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_PRESSED
, 0xe4);
367 } else if ((key
->oldState
& 0x10) && !(key
->keyNew
[0] & 0x10)) {
368 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_RELEASED
, 0xe4);
371 if ((key
->keyNew
[0] & 0x04) && !(key
->oldState
& 0x04)) {
372 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_PRESSED
, 0xe2);
373 } else if ((key
->oldState
& 0x04) && !(key
->keyNew
[0] & 0x04)) {
374 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_RELEASED
, 0xe2);
377 if ((key
->keyNew
[0] & 0x40) && !(key
->oldState
& 0x40)) {
378 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_PRESSED
, 0xe6);
379 } else if ((key
->oldState
& 0x40) && !(key
->keyNew
[0] & 0x40)) {
380 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_RELEASED
, 0xe6);
383 if ((key
->keyNew
[0] & 0x08) && !(key
->oldState
& 0x08)) {
384 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_PRESSED
, 0xe3);
385 } else if ((key
->oldState
& 0x08) && !(key
->keyNew
[0] & 0x08)) {
386 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_RELEASED
, 0xe3);
389 if ((key
->keyNew
[0] & 0x80) && !(key
->oldState
& 0x80)) {
390 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_PRESSED
, 0xe7);
391 } else if ((key
->oldState
& 0x80) && !(key
->keyNew
[0] & 0x80)) {
392 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_RELEASED
, 0xe7);
395 for (i
= 2; i
< 8; i
++)
397 if (key
->keyOld
[i
] > 3 && memchr(key
->keyNew
+ 2, key
->keyOld
[i
], 6) == NULL
)
399 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_RELEASED
, key
->keyOld
[i
]);
401 if (key
->keyNew
[i
] > 3 && memchr(key
->keyOld
+ 2, key
->keyNew
[i
], 6) == NULL
)
403 USBKeyboard_SubmitEvent(key
, USBKEYBOARD_PRESSED
, key
->keyNew
[i
]);
406 memcpy(key
->keyOld
, key
->keyNew
, 8);
407 key
->oldState
= key
->keyNew
[0];
412 s32
USBKeyboard_SetLed(USBKeyboard
*key
, const USBKeyboard_led led
, bool on
)
415 key
->leds
= key
->leds
| (1 << led
);
417 key
->leds
= key
->leds
& (255 ^ (1 << led
));
419 if (USBKeyboard_Set_OutputReport_Ctrl(key
)<0)
426 s32
USBKeyboard_ToggleLed(USBKeyboard
*key
, const USBKeyboard_led led
)
428 key
->leds
= key
->leds
^ (1 << led
);
429 if (USBKeyboard_Set_OutputReport_Ctrl(key
)<0)
434 //Set the callback function which will handle the keyboard events
435 void USBKeyboard_SetCB(USBKeyboard
* key
,eventcallback cb
, void* data
)