Keyboard lights, TLB shootdowns, battery in sysfs, /proc/pid/maps
Caps, Num and Scroll Lock now light their LEDs on PS/2 and USB keyboards, share one state between keyboards, and stop toggling on key repeat. X sets them through evdev writes while it holds the keyboard. Unmapping memory in a process with threads on other CPUs now flushes their TLBs with an IPI. Without it a freed page stayed reachable through stale translations, which corrupted Epiphany's heap on SMP. ACPI batteries and AC adapters appear under /sys/class/power_supply. /proc/<pid>/maps lists file mappings, and a process killed by a fault names the file and offset it died in. r8169 gets a 256-entry RX ring. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
This commit is contained in:
parent
73dcea7496
commit
438e7af141
18 changed files with 945 additions and 9 deletions
|
|
@ -43,6 +43,7 @@ struct hfield {
|
|||
|
||||
struct hid {
|
||||
int in_use;
|
||||
struct usb_dev *dev;
|
||||
int proto; // USB_HID_PROTO_KEYBOARD, _MOUSE or _TABLET
|
||||
uchar prev[8]; // the previous report, for edge detection
|
||||
|
||||
|
|
@ -248,6 +249,13 @@ keyboard_report(struct hid *h, const uchar *rep, int len)
|
|||
|
||||
keyboard_events(h->prev, rep);
|
||||
|
||||
// A lock key let go: the next press toggles again.
|
||||
for(i = 2; i < 8; i++){
|
||||
uchar was = h->prev[i];
|
||||
if((was == 0x39 || was == 0x53 || was == 0x47) && !was_down(rep, was))
|
||||
kbd_lock_key(was == 0x39 ? CAPSLOCK : was == 0x53 ? NUMLOCK : SCROLLLOCK, 0);
|
||||
}
|
||||
|
||||
// Grabbed: the events above still went to /dev/input/event0, but nothing
|
||||
// reaches the console. Note prev[] is updated before returning, or the next
|
||||
// report would look like every held key had just been pressed again.
|
||||
|
|
@ -264,11 +272,19 @@ keyboard_report(struct hid *h, const uchar *rep, int len)
|
|||
if(was_down(h->prev, usage))
|
||||
continue; // still held from last time, not a new press
|
||||
|
||||
if(usage == 0x39 || usage == 0x53 || usage == 0x47){
|
||||
kbd_lock_key(usage == 0x39 ? CAPSLOCK : usage == 0x53 ? NUMLOCK : SCROLLLOCK, 1);
|
||||
continue;
|
||||
}
|
||||
if(usage >= 0x39){
|
||||
if((c = hid_special(usage, mods)) == 0)
|
||||
continue;
|
||||
} else {
|
||||
c = (mods & HID_MOD_SHIFT) ? hid_shifted[usage] : hid_unshifted[usage];
|
||||
// Caps lock shifts letters only, as on every keyboard.
|
||||
int shifted = (mods & HID_MOD_SHIFT) != 0;
|
||||
if((kbd_lock_state() & CAPSLOCK) && usage >= 0x04 && usage <= 0x1D)
|
||||
shifted = !shifted;
|
||||
c = shifted ? hid_shifted[usage] : hid_unshifted[usage];
|
||||
if(c == 0)
|
||||
continue;
|
||||
}
|
||||
|
|
@ -305,6 +321,39 @@ keyboard_report(struct hid *h, const uchar *rep, int len)
|
|||
consoleintr(usb_kbd_getc);
|
||||
}
|
||||
|
||||
// The lights every USB keyboard should show, in HID's order (Num, Caps,
|
||||
// Scroll), and what was last sent. Set from interrupt context; sent from
|
||||
// usb_hid_tick, which runs on a thread and may wait for a control transfer.
|
||||
static volatile int leds_want = -1;
|
||||
static int leds_sent = -1;
|
||||
|
||||
void
|
||||
hid_leds_want(int bits)
|
||||
{
|
||||
leds_want = bits;
|
||||
}
|
||||
|
||||
static void
|
||||
hid_send_leds(int bits)
|
||||
{
|
||||
for(int i = 0; i < NHID; i++){
|
||||
struct hid *h = &hids[i];
|
||||
if(!h->in_use || !h->dev ||
|
||||
!(h->rkbd || h->proto == USB_HID_PROTO_KEYBOARD))
|
||||
continue;
|
||||
// SET_REPORT, output report: one byte of lights, under the keyboard's
|
||||
// report ID when its reports carry one.
|
||||
struct usb_setup s;
|
||||
uchar b = (uchar)bits;
|
||||
s.bmRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
|
||||
s.bRequest = 0x09;
|
||||
s.wValue = (2 << 8) | (h->rkbd ? h->kbd_id : 0);
|
||||
s.wIndex = h->dev->iface.bInterfaceNumber;
|
||||
s.wLength = 1;
|
||||
h->dev->ops->control(h->dev, &s, &b, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
usb_hid_tick(void)
|
||||
{
|
||||
|
|
@ -312,6 +361,11 @@ usb_hid_tick(void)
|
|||
|
||||
if(!kqinit)
|
||||
return;
|
||||
int want = leds_want;
|
||||
if(want >= 0 && want != leds_sent){
|
||||
leds_sent = want;
|
||||
hid_send_leds(want);
|
||||
}
|
||||
acquire(&kqlock);
|
||||
if(krep.c && (int)(ticks - krep.at) >= 0){
|
||||
c = krep.c;
|
||||
|
|
@ -870,7 +924,9 @@ hid_probe(struct usb_dev *dev)
|
|||
return -1;
|
||||
|
||||
h->in_use = 1;
|
||||
h->dev = dev;
|
||||
dev->drvdata = h;
|
||||
leds_sent = -1; // a new keyboard gets the current lights
|
||||
dev->complete = hid_complete;
|
||||
|
||||
// Arm the first transfer. Until a TRB is waiting on the endpoint the device
|
||||
|
|
|
|||
Loading…
Reference in a new issue