* First go at implementing key repeat support - not yet tested, though.
* Fixed some potential crashing bugs: an assert() is no replacement for checking the result of an allocation!!! * More minor cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18258 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -331,6 +331,10 @@ create_device(const usb_device *dev, const usb_interface_info *ii,
|
||||
device->cbuf = cbuf_init(384);
|
||||
device->is_keyboard = isKeyboard;
|
||||
|
||||
// default values taken from the PS/2 driver
|
||||
device->repeat_rate = ((31 - 0x0b) * 280) / 31 + 20;
|
||||
device->repeat_delay = 500000;
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
@@ -352,7 +356,39 @@ remove_device (hid_device_info *device)
|
||||
}
|
||||
|
||||
|
||||
/* driver cookie (per open) */
|
||||
static void
|
||||
write_key(hid_device_info *device, uint32 key, bool down)
|
||||
{
|
||||
raw_key_info raw;
|
||||
raw.be_keycode = key;
|
||||
raw.is_keydown = down;
|
||||
raw.timestamp = system_time();
|
||||
|
||||
cbuf_putn(device->cbuf, &raw, sizeof(raw_key_info));
|
||||
release_sem_etc(device->sem_cb, 1, B_DO_NOT_RESCHEDULE);
|
||||
}
|
||||
|
||||
|
||||
static int32
|
||||
timer_repeat_hook(struct timer *timer)
|
||||
{
|
||||
hid_device_info *device = ((struct hid_repeat_timer *)timer)->device;
|
||||
|
||||
write_key(device, device->repeat_timer.key, true);
|
||||
return B_HANDLED_INTERRUPT;
|
||||
}
|
||||
|
||||
|
||||
static int32
|
||||
timer_delay_hook(struct timer *timer)
|
||||
{
|
||||
hid_device_info *device = ((struct hid_repeat_timer *)timer)->device;
|
||||
|
||||
add_timer(&device->repeat_timer.timer, timer_repeat_hook, device->repeat_rate,
|
||||
B_PERIODIC_TIMER);
|
||||
return B_HANDLED_INTERRUPT;
|
||||
}
|
||||
|
||||
|
||||
// here we don't need to follow a report descriptor for typical keyboards
|
||||
// TODO : but we should for keypads for example because they aren't boot keyboard devices !
|
||||
@@ -360,21 +396,14 @@ remove_device (hid_device_info *device)
|
||||
static void
|
||||
interpret_kb_buffer(hid_device_info *device)
|
||||
{
|
||||
raw_key_info info;
|
||||
uint8 modifiers = ((uint8*)device->buffer)[0];
|
||||
uint8 bits = device->last_buffer[0] ^ modifiers;
|
||||
uint32 i, j;
|
||||
|
||||
info.timestamp = device->timestamp;
|
||||
|
||||
if (bits) {
|
||||
for (j = 0; bits; j++, bits >>= 1) {
|
||||
if (bits & 1) {
|
||||
info.be_keycode = modifier_table[j];
|
||||
info.is_keydown = (modifiers >> j) & 1;
|
||||
cbuf_putn(device->cbuf, &info, sizeof(info));
|
||||
release_sem_etc(device->sem_cb, 1, B_DO_NOT_RESCHEDULE);
|
||||
}
|
||||
if (bits & 1)
|
||||
write_key(device, modifier_table[j], (modifiers >> j) & 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -392,18 +421,23 @@ interpret_kb_buffer(hid_device_info *device)
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
info.be_keycode = key_table[((uint8*)device->buffer)[i]];
|
||||
if (info.be_keycode == KEY_Pause && modifiers & 1)
|
||||
info.be_keycode = KEY_Break;
|
||||
if (info.be_keycode == 0xe && modifiers & 1)
|
||||
info.be_keycode = KEY_SysRq;
|
||||
if (info.be_keycode == 0) {
|
||||
uint32 key = key_table[((uint8*)device->buffer)[i]];
|
||||
if (key == KEY_Pause && modifiers & 1)
|
||||
key = KEY_Break;
|
||||
else if (key == 0xe && modifiers & 1)
|
||||
key = KEY_SysRq;
|
||||
else if (key == 0) {
|
||||
// unmapped key
|
||||
info.be_keycode = 0x200000 + ((uint8*)device->buffer)[i];
|
||||
key = 0x200000 + ((uint8*)device->buffer)[i];
|
||||
}
|
||||
info.is_keydown = 1;
|
||||
cbuf_putn(device->cbuf, &info, sizeof(info));
|
||||
release_sem_etc(device->sem_cb, 1, B_DO_NOT_RESCHEDULE);
|
||||
|
||||
write_key(device, key, true);
|
||||
|
||||
// repeat handling
|
||||
cancel_timer(&device->repeat_timer.timer);
|
||||
device->repeat_timer.key = key;
|
||||
add_timer(&device->repeat_timer.timer, timer_delay_hook,
|
||||
device->repeat_delay, B_ONE_SHOT_RELATIVE_TIMER);
|
||||
}
|
||||
} else
|
||||
break;
|
||||
@@ -424,18 +458,18 @@ interpret_kb_buffer(hid_device_info *device)
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
info.be_keycode = key_table[((uint8*)device->last_buffer)[i]];
|
||||
if (info.be_keycode == KEY_Pause && modifiers & 1)
|
||||
info.be_keycode = KEY_Break;
|
||||
if (info.be_keycode == 0xe && modifiers & 1)
|
||||
info.be_keycode = KEY_SysRq;
|
||||
if (info.be_keycode == 0) {
|
||||
uint32 key = key_table[((uint8*)device->last_buffer)[i]];
|
||||
if (key == KEY_Pause && modifiers & 1)
|
||||
key = KEY_Break;
|
||||
else if (key == 0xe && modifiers & 1)
|
||||
key = KEY_SysRq;
|
||||
else if (key == 0) {
|
||||
// unmapped key
|
||||
info.be_keycode = 0x200000 + ((uint8*)device->last_buffer)[i];
|
||||
key = 0x200000 + ((uint8*)device->last_buffer)[i];
|
||||
}
|
||||
info.is_keydown = 0;
|
||||
cbuf_putn(device->cbuf, &info, sizeof(info));
|
||||
release_sem_etc(device->sem_cb, 1, B_DO_NOT_RESCHEDULE);
|
||||
|
||||
write_key(device, key, false);
|
||||
cancel_timer(&device->repeat_timer.timer);
|
||||
}
|
||||
} else
|
||||
break;
|
||||
@@ -480,7 +514,7 @@ sign_extend(int value, int size)
|
||||
|
||||
|
||||
static void
|
||||
interpret_ms_buffer(hid_device_info *device)
|
||||
interpret_mouse_buffer(hid_device_info *device)
|
||||
{
|
||||
mouse_movement info;
|
||||
uint8 *report = (uint8*)device->buffer;
|
||||
@@ -571,7 +605,7 @@ usb_callback(void *cookie, uint32 busStatus,
|
||||
interpret_kb_buffer(device);
|
||||
memcpy(device->last_buffer, device->buffer, device->total_report_size);
|
||||
} else
|
||||
interpret_ms_buffer(device);
|
||||
interpret_mouse_buffer(device);
|
||||
|
||||
release_sem (device->sem_lock);
|
||||
}
|
||||
@@ -667,7 +701,9 @@ hid_device_added(const usb_device *dev, void **cookie)
|
||||
desc_len = hid_desc->descriptor_info[0].descriptor_length;
|
||||
free(hid_desc);
|
||||
rep_desc = malloc(desc_len);
|
||||
assert (rep_desc != NULL);
|
||||
if (rep_desc == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
status = usb->send_request(dev,
|
||||
USB_REQTYPE_INTERFACE_IN | USB_REQTYPE_STANDARD,
|
||||
USB_REQUEST_GET_DESCRIPTOR,
|
||||
@@ -716,7 +752,12 @@ hid_device_added(const usb_device *dev, void **cookie)
|
||||
|
||||
num_items = desc_len; /* XXX */
|
||||
items = malloc(sizeof (decomp_item) * num_items);
|
||||
assert (items != NULL);
|
||||
if (items == NULL) {
|
||||
// TODO: free device
|
||||
free(rep_desc);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
decompose_report_descriptor(rep_desc, desc_len, items, &num_items);
|
||||
free(rep_desc);
|
||||
|
||||
@@ -741,7 +782,6 @@ hid_device_added(const usb_device *dev, void **cookie)
|
||||
|
||||
/* get initial state */
|
||||
|
||||
|
||||
status = usb->send_request(dev,
|
||||
USB_REQTYPE_INTERFACE_IN | USB_REQTYPE_CLASS,
|
||||
USB_REQUEST_HID_GET_REPORT,
|
||||
@@ -769,7 +809,6 @@ hid_device_added(const usb_device *dev, void **cookie)
|
||||
|
||||
*cookie = device;
|
||||
DPRINTF_INFO ((MY_ID "added %s\n", device->name));
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -66,6 +66,12 @@ void cbuf_unlock(cbuffer *, cpu_status);
|
||||
|
||||
struct driver_cookie;
|
||||
|
||||
struct hid_repeat_timer {
|
||||
struct timer timer;
|
||||
struct hid_device_info *device;
|
||||
uint32 key;
|
||||
};
|
||||
|
||||
typedef struct hid_device_info {
|
||||
/* list structure */
|
||||
struct hid_device_info *next;
|
||||
@@ -99,6 +105,10 @@ typedef struct hid_device_info {
|
||||
bigtime_t timestamp;
|
||||
uint flags;
|
||||
bool is_keyboard;
|
||||
|
||||
struct hid_repeat_timer repeat_timer;
|
||||
bigtime_t repeat_delay;
|
||||
bigtime_t repeat_rate;
|
||||
} hid_device_info;
|
||||
|
||||
/* hid.c */
|
||||
|
||||
Reference in New Issue
Block a user