Disclaimer: this is pending for v4.21 and thus not yet in any kernel release.

Most wheel mice have a physical feature to stop the wheel from spinning freely. That feature is called detents, notches, wheel clicks, stops, or something like that. On your average mouse that is 24 wheel clicks per full rotation, resulting in the wheel rotating by 15 degrees before its motion is arrested. On some other mice that angle is 18 degrees, so you get 20 clicks per full rotation.

Of course, the world wouldn't be complete without fancy hardware features. Over the last 10 or so years devices have added free-wheeling scroll wheels or scroll wheels without distinct stops. In many cases wheel behaviour can be configured on the device, e.g. with Logitech's HID++ protocol. A few weeks back, Harry Cutts from the chromium team sent patches to enable Logitech high-resolution wheel scrolling in the kernel. Succinctly, these patches added another axis next to the existing REL_WHEEL named REL_WHEEL_HI_RES. Where available, the latter axis would provide finer-grained scroll information than the click-by-click REL_WHEEL. At the same time I accidentally stumbled across the documentation for the HID Resolution Multiplier Feature. A few patch revisions later and we now have everything queued up for v4.21. Below is a summary of the new behaviour.

The kernel will continue to provide REL_WHEEL as axis for "wheel clicks", just as before. This axis provides the logical wheel clicks, (almost) nothing changes here. In addition, a REL_WHEEL_HI_RES axis is available which allows for finer-grained resolution. On this axis, the magic value 120 represents one logical traditional wheel click but a device may send a fraction of 120 for a smaller motion. Userspace can either accumulate the values until it hits a full 120 for one wheel click or it can scroll by a few pixels on each event for a smoother experience. The same principle is applied to REL_HWHEEL and REL_HWHEEL_HI_RES for horizontal scroll wheels (which these days is just tilting the wheel). The REL_WHEEL axis is now emulated by the kernel and simply sent out whenever we have accumulated 120.

Important to note: REL_WHEEL and REL_HWHEEL are now legacy axes and should be ignored by code handling the respective high-resolution version.

The magic value of 120 is taken directly from Windows. That value was chosen because it has a good number of integer factors, so dividing 120 by whatever multiplier the mouse uses gives you a integer fraction of 120. And because HW manufacturers want it to work on Windows, we can rely on them doing it right, provided we use the same approach.

There are two implementations that matter. Harry's patches enable the high-resolution scrolling on Logitech mice which seem to mostly have a multiplier of 8 (i.e. REL_WHEEL_HI_RES will send eight events with a value of 15 before REL_WHEEL sends 1 click). There are some interesting side-effects with e.g. the MX Anywhere 2S. In high-resolution mode with a multiplier of 8, a single wheel movement does not always give us 8 events, the firmware does its own magic here. So we have some emulation code in place with the goal of making the REL_WHEEL event happen on the mid-point of a wheel click motion. The exact point can shift a bit when the device sends 7 events instead of 8 so we have a few extra bits in place to reset after timeouts and direction changes to make sure the wheel behaviour is as consistent as possible.

The second implementation is for the generic HID protocol. This was all added for Windows Vista, so we're only about a decade behind here. Microsoft got the Resolution Multiplier feature into the official HID documentation (possibly in the hope that other HW manufacturers implement it which afaict didn't happen). This feature effectively provides a fixed value multiplier that the device applies in hardware when enabled. It's basically the same as the Logitech one except it's set through a HID feature instead of a vendor-specific protocol. On the devices tested so far (all Microsoft mice because no-one else seems to implement this) the multipliers vary a bit, ranging from 4 to 12. And the exact behaviour varies too. One mouse behaves correctly (Microsoft Comfort Optical Mouse 3000) and sends more events than before. Other mice just send the multiplied value instead of the normal value, so nothing really changes. And at least one mouse (Microsoft Sculpt Ergonomic) sends the tilt-wheel values more frequently and with a higher value. So instead of one event with value 1 every X ms, we now get an event with value 3 every X/4 ms. The mice tested do not drop events like the Logitech mice do, so we don't need fancy emulation code here. Either way, we map this into the 120 range correctly now, so userspace gets to benefit.

As mentioned above, the Resolution Multiplier HID feature was introduced for Windows Vista which is... not the most recent release. I have a strong suspicion that Microsoft dumped this feature as well, the most recent set of mice I have access to don't provide the feature anymore (they have vendor-private protocols that we don't know about instead). So the takeaway for all this is: if you have a Logitech mouse, you'll get higher-resolution scrolling on v4.21. If you have a Microsoft mouse a few years old, you may get high-resolution wheel scrolling if the device supports it. Any other vendor or a new Microsoft mouse, you don't get it.

Coincidentally, if you know anyone at Microsoft who can provide me with the specs for their custom protocol, I'd appreciate it. We'd love to have support for it both in libratbag and in the kernel. Or any other vendor, come to think of it.

Posted Wed Dec 12 04:27:00 2018 Tags:
And by "tube" I mean: I stepped out of my door and some idiot on a scooter rammed into me and went flying. He had been speeding down the sidewalk like a foot from the wall. As he lay sprawled in his yardsale and I tried to determine whether I was bleeding I said, "This is why I hate those things!"


Still lying on the ground, he said, "But it's not my fault!"

"Fuck you!" I explained. "You were going 20 miles an hour on the fucking sidewalk!"

This is when the guy at the glass shop started laughing. I guess you can't really say you were a part of San Francisco 2018 until a techbro on a scooter has slammed into you and then blamed you for it.

How to Recycle your E-scooter:

The city and the e-scooter companies have been working very hard to find a solution to the e-scooter problem, and in response to public demand, they have placed escooter docking stations all over the city for your convenience. When you see an e-scooter on the sidewalk, calmly walk up to it, pick it up, and place it on the nearest docking station, also known as a 'scootypods' (they're still focus grouping that title).

If a docking station does not have the recycling symbol on it, simply slot the scooter through the top of the docking station as pictured. [...]

When you're done riding an escooter, always remember to D.U.M.P

  • Don't panic
  • Understand that you are part of the problem
  • Mobilize your legs
  • Place escooter in the trash

Previously, previously, previously, previously, previously.

Posted Tue Dec 11 19:45:03 2018 Tags:
And by "tube" I mean: I stepped out of my door and some idiot on a scooter rammed into me and went flying. He had been speeding down the sidewalk like a foot from the wall. As he lay sprawled in his yardsale and I tried to determine whether I was bleeding I said, "This is why I hate those things!"


Still lying on the ground, he said, "But it's not my fault!"

"Fuck you!" I explained. "You were going 20 miles an hour on the fucking sidewalk!"

This is when the guy at the glass shop started laughing. I guess you can't really say you were a part of San Francisco 2018 until a techbro on a scooter has slammed into you and then blamed you for it.

How to Recycle your E-scooter:

The city and the e-scooter companies have been working very hard to find a solution to the e-scooter problem, and in response to public demand, they have placed escooter docking stations all over the city for your convenience. When you see an e-scooter on the sidewalk, calmly walk up to it, pick it up, and place it on the nearest docking station, also known as a 'scootypods' (they're still focus grouping that title).

If a docking station does not have the recycling symbol on it, simply slot the scooter through the top of the docking station as pictured. [...]

When you're done riding an escooter, always remember to D.U.M.P

  • Don't panic
  • Understand that you are part of the problem
  • Mobilize your legs
  • Place escooter in the trash

Previously, previously, previously, previously, previously.

Posted Tue Dec 11 19:45:03 2018 Tags:

This time we're digging into HID - Human Interface Devices and more specifically the protocol your mouse, touchpad, joystick, keyboard, etc. use to talk to your computer.

Remember the good old days where you had to install a custom driver for every input device? Remember when PS/2 (the protocol) had to be extended to accommodate for mouse wheels, and then again for five button mice. And you had to select the right protocol to make it work. Yeah, me neither, I tend to suppress those memories because the world is awful enough as it is.

As users we generally like devices to work out of the box. Hardware manufacturers generally like to add bits and bobs because otherwise who would buy that new device when last year's device looks identical. This difference in needs can only be solved by one superhero: Committee-man, with the superpower to survive endless meetings and get RFCs approved.

Many many moons ago, when USB itself was in its infancy, Committee man and his sidekick Caffeine boy got the USB consortium agree on a standard for input devices that is so self-descriptive that operating systems (Win95!) can write one driver that can handle this year's device, and next year's, and so on. No need to install extra drivers, your device will just work out of the box. And so HID was born. This may only an approximate summary of history.

Originally HID was designed to work over USB. But just like Shrek the technology world is obsessed with layers so these days HID works over different transport layers. HID over USB is what your mouse uses, HID over i2c may be what your touchpad uses. HID works over Bluetooth and it's celebrity-diet version BLE. Somewhere, someone out there is very slowly moving a mouse pointer by sending HID over carrier pigeons just to prove a point. Because there's always that one guy.

HID is incredibly simple in that the static description of the device can just be bytes burnt into the ROM like the Australian sun into unprepared English backpackers. And the event frames are often an identical series of bytes where every bit is filled in by the firmware according to the axis/buttons/etc.

HID is incredibly complicated because parsing it is a stack-based mental overload. Each individual protocol item is simple but getting it right and all into your head is tricky. Luckily, I'm here for you to make this simpler to understand or, failing that, at least more entertaining.

As said above, the purpose of HID is to make devices describe themselves in a generic manner so that you can have a single driver handle any input device. The idea is that the host parses that standard protocol and knows exactly how the device will behave. This has worked out great, we only have around 200 files dealing with vendor- and hardware-specific HID quirks as of v4.20.

HID messages are Reports. And to know what a Report means and how to interpret it, you need a Report Descriptor. That Report Descriptor is static and contains a series of bytes detailing "what" and "where", i.e. what a sequence of bits represents and where to find those bits in the Report. So let's try and parse one of Report Descriptors, let's say for a fictional mouse with a few buttons. How exciting, we're at the forefront of innovation here.

The Report Descriptor consists of a bunch of Items. A parser reads the next Item, processes the information within and moves on. Items are small (1 byte header, 0-4 bytes payload) and generally only apply exactly one tiny little bit of information. You need to accumulate several items to build up enough information to actually know what's happening.

The "what" question of the Report Descriptor is answered with the so-called Usage. This could be something simple like X or Y (0x30 and 0x31) or something more esoteric like System Menu Exit (0x88). A Usage is 16 bits but all Usages are grouped into so-called Usage Pages. A Usage Page too is a 16 bit value and together they form the 32-bit value that tells us what the device can do. Examples:


0001 0031 # Generic Desktop, Y
0001 0088 # Generic Desktop, System Menu Exit
0003 0005 # VR Controls, Head Tracker
0003 0006 # VR Controls, Head Mounted Display
0004 0031 # Keyboard, Keyboard \ and |
Note how the Usage in the last item is the same as the first one, without the Usage Page you will mix things up. It helps if you always think of as the Usage as a 32-bit number. For your kids' bed-time story time, here are the HID Usage Tables from 2004 and the approved HID Usage Table Review Requests of the last decade. Because nothing puts them to sleep quicker than droning on about hex numbers associated with remote control buttons.

To successfully interpret a Report from the device, you need to know which bits have which Usage associated with them. So let's go back to our innovative mouse. We would want a report descriptor with 6 items like this:


Usage Page (Generic Desktop)
Usage (X)
Report Size (16)
Usage Page (Generic Desktop)
Usage (Y)
Report Size (16)
This basically tells the host: X and Y both have 16 bits. So if we get a 4-byte Report from the device, we know two bytes are for X, two for Y.

HID was invented when a time when bits were more expensive than printer ink, so we can't afford to waste any bits (still the case because who would want to spend an extra penny on more ROM). HID makes use of so-called Global items, once those are set their value applies to all following items until changed. Usage Page and Report Size are such Global items, so the above report descriptor is really implemented like this:


Usage Page (Generic Desktop)
Usage (X)
Usage (Y)
Report Count (2)
Report Size (16)
Input (Data,Var,Rel)
The Report Count just tells us that 2 fields of the current Report Size are coming up. We have two usages, two fields, and 16 bits each so we know what to do. The Input item is sort-of the marker for the end of the stack, it basically tells us "process what you've seen so far", together with a few flags. Rel in this case means that the Usages are relative. Oh, and Input means that this is data from device to host. Output would be data from host to device, e.g. to set LEDs on a keyboard. There's also Feature which indicates configurable items.

Buttons on a device are generally just numbered so it'd be monumental 16-bits-at-a-time waste to have HID send Usage (Button1), Usage (Button2), etc. for every button on the device. HID instead provides a Usage Minimum and Usage Maximumto sequentially order them. This looks like this:


Usage Page (Button)
Usage Minimum (1)
Usage Maximum (5)
Report Count (5)
Report Size (1)
Input (Data,Var,Abs)
So we have 5 buttons here and each button has one bit. Note how the buttons are Abs because a button state is not a relative value, it's either down or up. HID is quite intolerant to Schrödinger's thought experiments.

Let's put the two things together and we have an almost-correct Report descriptor:


Usage Page (Button)
Usage Minimum (1)
Usage Maximum (5)
Report Count (5)
Report Size (1)
Input (Data,Var,Abs)

Report Size (3)
Report Count (1)
Input (Cnst,Arr,Abs)

Usage Page (Generic Desktop)
Usage (X)
Usage (Y)
Report Count (2)
Report Size (16)
Input (Data,Var,Rel)
New here is Cnst. This signals that the bits have a constant value, thus don't need a Usage and basically don't matter (haha. yeah, right. in theory). Linux does indeed ignore those. Cnst is used for padding to align on byte boundaries - 5 bits for buttons plus 3 bits padding make 8 bits. Which makes one byte as everyone agrees except for granddad over there in the corner. I don't know how he got in.

Were we to get a 5-byte Report from the device, we'd parse it approximately like this:


button_state = byte[0] & 0x1f
x = bytes[1] | (byte[2] << 8)
y = bytes[3] | (byte[4] << 8)
Hooray, we're almost ready. Except not. We may need more info to correctly interpret the data within those reports.

The Logical Minimum and Logical Maximum specify the value range of the actual data. We need this to tell us whether the data is signed and what the allowable range is. Together with the Physical Minimumand the Physical Maximum they specify what the values really mean. In the simple case:


Usage Page (Generic Desktop)
Usage (X)
Usage (Y)
Report Count (2)
Report Size (16)
Logical Minimum (-32767)
Logical Maximum (32767)
Input (Data,Var,Rel)
This just means our x/y data is signed. Easy. But consider this combination:

...
Logical Minimum (0)
Logical Maximum (1)
Physical Minimum (1)
Physical Maximum (12)
This means that if the bit is 0, the effective value is 1. If the bit is 1, the effective value is 12.

Note that the above is one report only. Devices may have multiple Reports, indicated by the Report ID. So our Report Descriptor may look like this:


Report ID (01)
Usage Page (Button)
Usage Minimum (1)
Usage Maximum (5)
Report Count (5)
Report Size (1)
Input (Data,Var,Abs)
Report Size (3)
Report Count (1)
Input (Cnst,Arr,Abs)

Report ID (02)
Usage Page (Generic Desktop)
Usage (X)
Usage (Y)
Report Count (2)
Report Size (16)
Input (Data,Var,Rel)
If we were to get a Report now, we need to check byte 0 for the Report ID so we know what this is. i.e. our single-use hard-coded parser would look like this:

if byte[0] == 0x01:
button_state = byte[1] & 0x1f
else if byte[0] == 0x02:
x = bytes[2] | (byte[3] << 8)
y = bytes[4] | (byte[5] << 8)
A device may use multiple Reports if the hardware doesn't gather all data within the same hardware bits. Now, you may ask: if I get fifteen reports, how should I know what belongs together? Good question, and lucky for you the HID designers are miles ahead of you. Report IDs are grouped into Collections.

Collections can have multiple types. An Application Collectiondescribes a set of inputs that make sense as a whole. Usually, every Report Descriptor must define at least one Application Collection but you may have two or more. For example, a a keyboard with integrated trackpoint should and/or would use two. This is how the kernel knows it needs to create two separate event nodes for the device. Application Collections have a few reserved Usages that indicate to the host what type of device this is. These are e.g. Mouse, Joystick, Consumer Control. If you ever wondered why you have a device named like "Logitech G500s Laser Gaming Mouse Consumer Control" this is the kernel simply appending the Application Collection's Usage to the device name.

A Physical Collection indicates that the data is collected at one physical point though what a point is is a bit blurry. Theoretical physicists will disagree but a point can be "a mouse". So it's quite common for all reports on a mouse to be wrapped in one Physical Collections. If you have a device with two sets of sensors, you'd have two collections to illustrate which ones go together. Physical Collections also have reserved Usages like Pointer or Head Tracker.

Finally, a Logical Collection just indicates that some bits of data belong together, whatever that means. The HID spec uses the example of buffer length field and buffer data but it's also common for all inputs from a mouse to be grouped together. A quick check of my mice here shows that Logitech doesn't wrap the data into a Logical Collection but Microsoft's firmware does. Because where would we be if we all did the same thing...

Anyway. Now that we know about collections, let's look at a whole report descriptor as seen in the wild:


Usage Page (Generic Desktop)
Usage (Mouse)
Collection (Application)
Usage Page (Generic Desktop)
Usage (Mouse)
Collection (Logical)
Report ID (26)
Usage (Pointer)
Collection (Physical)
Usage Page (Button)
Usage Minimum (1)
Usage Maximum (5)
Report Count (5)
Report Size (1)
Logical Minimum (0)
Logical Maximum (1)
Input (Data,Var,Abs)
Report Size (3)
Report Count (1)
Input (Cnst,Arr,Abs)
Usage Page (Generic Desktop)
Usage (X)
Usage (Y)
Report Count (2)
Report Size (16)
Logical Minimum (-32767)
Logical Maximum (32767)
Input (Data,Var,Rel)
Usage (Wheel)
Physical Minimum (0)
Physical Maximum (0)
Report Count (1)
Report Size (16)
Logical Minimum (-32767)
Logical Maximum (32767)
Input (Data,Var,Rel)
End Collection
End Collection
End Collection
We have one Application Collection (Generic Desktop, Mouse) that contains one Logical Collection (Generic Desktop, Mouse). That contains one Physical Collection (Generic Desktop, Pointer). Our actual Report (and we have only one but it has the decimal ID 26) has 5 buttons, two 16-bit axes (x and y) and finally another 16 bit axis for the Wheel. This device will thus send 8-byte reports and our parser will do:

if byte[0] != 0x1a: # it's decimal in the above descriptor
error, should be 26
button_state = byte[1] & 0x1f
x = byte[2] | (byte[3] << 8)
y = byte[4] | (byte[5] << 8)
wheel = byte[6] | (byte[7] << 8)
That's it. Now, obviously, you can't write a parser for every HID descriptor out there so your actual parsing code needs to be generic. The Linux kernel does exactly that and so does everything else that needs to parse HID. There's a huge variety in devices out there, all with HID descriptors that may or may not be correct. As with so much in life, correct HID implementations are often defined by "whatever Windows accepts" so if you like playing catch, Linux development is for you.

Oh, in case you just got a bit too optimistic about the state of the world: HID allows for vendor-defined usages. Which does exactly what you'd think it does, it hides vendor-specific protocol inside what should be a generic protocol. There are devices with hidden report IDs that you can only unlock by sending the right magic sequence to the report and/or by defeating the boss on Level 4. Usually those devices present themselves as basic/normal devices over HID but if you know the magic sequence you get to use *gasp* all buttons. Or access the device-specific configuration features. Logitech's HID++ is just one example here but at least that's one where we have most of the specs available.

The above describes how to parse the HID report descriptor and interpret the reports. But what happens once you have a HID report correctly parsed? In the case of the Linux kernel, once the report descriptor is parsed evdev nodes are created (one per Application Collection, more or less). As the Reports come in, they are mapped to evdev codes and the data appears on the evdev node. That's where userspace like libinput can pick it up. That bit is actually quite simple (mostly anyway).

The above output was generated with the tools from the hid-tools repository. Go forth and hid-record.

Posted Tue Dec 11 05:56:00 2018 Tags:
Posted Tue Dec 11 00:00:00 2018 Tags:

The Ewaiwe family are Palestinians that live in Hebron. Fanatical Israeli "settlers" are trying to push Palestinians out of Hebron, one by one. So they attack the Ewaiwe home, over and over, trying to drive them out.

"Settlers" attacks now target elementary schools as well as olive trees and homes.

Posted Tue Dec 11 00:00:00 2018 Tags:

The pathway to a Green New Deal, if fully designed by early 2020 as it should be, will give Americans an opportunity to make climate safety a major election issue.

Posted Tue Dec 11 00:00:00 2018 Tags:

Large farms spray herbicides to kill the crop plants in order to take off their seeds more efficiently. The result is more herbicides in our food. Since herbicides affect gut bacteria, that can effect human health.

Posted Tue Dec 11 00:00:00 2018 Tags:

Microplastics poison periwinkles so that they cannot protect themselves from being eaten.

Posted Tue Dec 11 00:00:00 2018 Tags:

PG&E, the electric company in most of California, seems to be going bankrupt because of expected liability for the burning of the town of Paradise. This provides an opportunity to convert it into a public agency, controlled by local people and putting excess funds into safety and the cities where it operates.

Posted Tue Dec 11 00:00:00 2018 Tags:

Tories are in effect eliminating gratis public education in the UK. Their budget cuts, and punishment of any school that is below average, have pushed schools to demand increasing amounts of "donations" from parents.

Posted Tue Dec 11 00:00:00 2018 Tags:

James Risen said: bad as Obama was on the issue of freedom of the press, the bullshitter is even worse.

Posted Tue Dec 11 00:00:00 2018 Tags:

US border thugs grasp at straws and loopholes to block reunion of refugee families.

Posted Tue Dec 11 00:00:00 2018 Tags:
Posted Tue Dec 11 00:00:00 2018 Tags:

From a book I've been reading:

    Power is certainly important, particularly in dictatorships, in places where constitutions, laws, unwritten rules, traditions and understandings don't count. But in a healthy democracy, power is a surprisingly limited element. And the unwritten conventions, understandings, forms of respect for how things are done, for how citizens relate to government and to each other, are surprisingly important. Why? Because if democracy is only power, then what we are left with is a system of deep distrust. Why? Because if only power matters - even if it is the result of an election - then the government feels that it has a mandate to do whatever it wants, that the law is there principally to serve power. If democracy is only about winning power and using it, then it has been deformed into a denial of society and of the idea of responsible citizenship.

    And that is the increasingly common characteristic of government, even in democracies. Only power matters. This is partly the outcome of government being de-intellectualized. Elections are now thought to be unsuitable moments for real debates over ideas. In between these elections the focus is on administrative problems - legalistic, managerial undertakings. In this case, real debates over ideas are unnecessary because the decision about power was taken on election night. There is nothing, therefore, to debate. Worse still, the efficient putting in place of programs to be administered can only be made inefficient by debate.

    And so we are witnessing a growth in the Napoleonic or Mussolinian corporatist idea that when citizens vote in an election, it is actually an all-purpose referendum or plebiscite. It is then the winner's job to get on with running things. First win an election, then administer as you wish. Omnibus bills are one of the ways you can speed things up; they are a great way to convert the deeply inefficient process of democracy, with all its thinking, debating and complex differences of opinion, into a sort of shop-floor system of utilitarian efficiency. Therefore, once elected, a government has broad, unlimited permission.

    [...]

    In any case, today's plebiscitary approach is both populist and anti-democratic. What it amounts to is this: We won the election. We have power. It is now a matter of administrative efficiency. We can do what we want.

        - John Ralson Saul, The Comeback, 2014

This finally put into words a concept I've been struggling with for a long time: the idea that ethics and responsibility come with (should come with) political power, and how they seem to be on the decline lately.

For example, I recently learned, to my horror, about the concept of a Frankenstein Veto, where in some U.S. states, the governor can just delete words (eg. "not") from a bill passed by the legislature, producing and then approving a bill with a completely different meaning than was intended.

The exact legal machinations of this are beside the point. The point is, politicians increasingly feel that they "first win an election, then administer as you wish." That almost sounds logical, so why does it feel so wrong?

Because it is wrong. The job of an elected official isn't to do whatever they want. It's to figure out what the people want (or need), and to deliver that, in accordance with principles and ethics. This is a surprisingly selfless expectation: sometimes the right thing to do is the opposite of what you want to do. And it can be hard to figure out what's right, which is why we have debates, and why we listen to our opponents in those debates, even when we have a majority and they're "merely" the opposition.

Even direct polling on issues doesn't always work, because sometimes issues are too subtle for the population to simply vote yes or no; that's why we elect representatives who will presumably do their homework, consult the right people, and figure out the right, complex answer. At least one thing is clear: if the legislature vigorously debates an issue and decides one thing, a governor passing a law that does the opposite - or even rejecting the one that was so carefully produced - is just not right.

I've been struck many times by the way the U.S. system of political "checks and balances" treats politicians like children: none of them can be trusted, so we must restrict them at every opportunity. The underlying assumption is that they will all operate without honour. As most of us eventually learn in our human relationships, if you treat people as children - or worse, as actively malicious adults - then they will tend to meet your expectations. The great irony is that in countries with less of a focus on checking "power" (such as Canada), politicians seem to abuse their power less often and less dramatically.

The above quote made me think that maybe the secret recipe is some combination of traditions, conventions, understanding, and respect. Maybe those are more effective balances to power than any system designed to simply neutralize it. And maybe this was obvious to the people who designed it, and we've forgotten, long ago.

Posted Sun Dec 9 12:14:41 2018 Tags:
Here's a video of the program, running in an emulator, and synchronized with the album. "Press any key at start of music":

This video shows the whole process of booting it up, along with more detail than you probably need to know about cassette tape audio fidelity:


In 1983, Pete Shelley's album XL•1 included as its final track a program for the Sinclair ZX Spectrum 8-bit home computer. To play it, you had to first copy the track from the vinyl record to cassette, wait several minutes for the computer to read the cassette, and then press the any key once you dropped the needle on the first track! Lyrics and visualizations ensued.

Here's the programmer's story: Joey Headen:

In late 1982 Pete had ordered a Sinclair Spectrum by mail order, and one of the first BASIC programs he wrote put up the lyrics to one of his songs prompted by key presses. [...] I spent most of Christmas 1982 learning machine code and disassembling the Spectrum ROM.

I didn't have an assembler for the Spectrum, I don't even know if one was available then, so all the code had to be converted into its hex equivalent and typed into the program. All the jumps and calls to subroutines had to be hand calculated as well! When the machine crashed it had to be restarted and the cassette tape program reloaded, usually taking at least 5 minutes. [...]

With only a few days before the album had to be finished, Pete still had two songs to complete, one of which only had a title. We had to wait for the songs to be completed, type in the lyrics off scraps of paper, and then synchronize the lyrics to the music. [...]

Once the album was finished and mixed we had to do the final version of the timing for the lyrics. This involved adding in the timings between each track on the final master version of the album. It was at this point that we noticed that there was as much as 5 seconds difference (over a 20-minute side of the album) between different one-inch tape machines in the studio. The implication of this was that home turntables and tape machines could get horribly out of synch with the program unless they had some sort of variable speed control. One solution to this problem would be to add speed control keys to the program, but it was too late to add any more code. [...]

Our work wasn't quite finished yet, as we had to cut the album. To our knowledge nobody had put a program on a 12-inch disc before, so we were breaking new ground. After the last music track of side 2 there was a locking groove to prevent the code from blasting through someone's speakers.

The only way to play the code was to physically lift the needle onto the last track. We cut one master disc and tested it on a Spectrum but it didn't work, so we had to reset some of the levels and try again. Luckily the second master disc worked fine and it could go to the pressing plant.

Previously, previously, previously, previously, previously, previously, previously, previously.

Posted Sat Dec 8 19:37:35 2018 Tags:
In case there was any lingering doubt about the scooter business model:

  1. Dump electronic junk onto the street;
  2. Abandon it and walk away as soon as any unit stops generating money;
  3. Shift the cost of collection, storage, and disposal onto the taxpayers.

I told you so!

These scooters were standard, off-the-shelf electric scooters made in China, loaded up with battery packs, motors, and a 'brain box' that has a GPS unit, a cellular modem, and a few more electronics that turn this dumb electric scooter into something you can ride via an app. Dropping electronic waste on cities around the country was not looked upon kindly by these municipalities, and right now there are hundreds of Bird and Lime scooters in towing yards, just waiting to be auctioned off to the highest bidder. [...]

Right now, humanbeing21 is in contact with a towing company that has well over a hundred Bird scooters on their lot, each accruing daily storage fees. Since these scooters only cost about $400 new, we're probably well past the time when it makes sense for Bird to pay to get them out of storage. This means they'll probably be heading for an auction where anyone can pick them up -- all of them -- for a hundred bucks or so.

Previously, previously, previously, previously, previously.

Posted Sat Dec 8 07:57:15 2018 Tags:
Because we live in the Stupidest Timeline, Mozilla find themselves needing to point out that MICROS~1 leaving the web browser market is bad for the web.

Stupidest. Stupidest, stupidest, stupidest timeline.

Mozilla Blog: Goodbye, EdgeHTML:

Microsoft is officially giving up on an independent shared platform for the internet. By adopting Chromium, Microsoft hands over control of even more of online life to Google. [...]

From a business point of view Microsoft's decision may well make sense. Google is so close to almost complete control of the infrastructure of our online lives that it may not be profitable to continue to fight this. [...] From a social, civic and individual empowerment perspective ceding control of fundamental online infrastructure to a single company is terrible. This is why Mozilla exists. We compete with Google not because it's a good business opportunity. We compete with Google because the health of the internet and online life depend on competition and choice. They depend on consumers being able to decide we want something better and to take action.

So that "this is why Mozilla exists" sentiment is great and all, but....

Remember back in the 90s when Gates was claiming that Internet Explorer was an inseparable part of the Windows operating system, and then someone asked him a question he couldn't answer: "Which part of Windows is Internet Explorer for Mac"?

Well, what part of "the health of the internet and online life depend on competition and choice" is served by Mozilla's partnership with vertically integrated, predatory multinational monopolists like Live Nation? Or by implementing DRM?

Previously, previously, previously, previously, previously.

Posted Sat Dec 8 02:49:47 2018 Tags:
I know that eel, bro:

It took several emails and phone calls before the decision was made to grab the eel and try pulling it out.

"There was only maybe two inches of the eel actually still sticking out of the nose, so it was very much akin to the magician's trick when they're pulling out the handkerchiefs and they keep coming and coming and coming," he said.

After less than a minute of tugging, a two-and-a-half-foot dead eel emerged from the seal's nostril.

Since then, Littnan said there have been at least three or four reported cases, and the most recent occurred this fall. In all the cases, the eels were removed successfully and the seals are "doing great," he said. None of the eels, however, survived. [...]

If monk seals could understand humans, Littnan said he has a message for them: "I would gently plead for them to stop."

Previously, previously, previously, previously, previously, previously, previously.

Posted Fri Dec 7 21:18:42 2018 Tags:

Orbital was the first band that I saw in San Francisco. It was 1990 and I crossed the bridge from Berkeley to see them at some club called The Bridge. I don't remember who the opener was -- maybe it was Consolidated? Someone like that -- but I was standing at the back by the sound booth when Orbital began, and they performed from the sound booth, so suddenly I was I the "front row", leaning into the window and watching these two nerdy bald guys with headlights on their glasses turn knobs and punch arcane numbers into the keypads of a really impressive stack of 1U rack-mount devices.

So then years later, I'm leaning against the Trocadero bar, probably at Death Guild, and I'm telling someone the Orbital story. "Yeah, I don't know where that club was... I hadn't lived here long...", I said. "There was a stage over there, and the bar was over there, and stairs were over there, and HEY WAIT A MINUTE it was this building!"

So it turns out that the Trocadero, which has been named that since the 70s, was renamed to "The Bridge" for like, six months in the middle of its 30 year history. Weird.

And then suddenly:

It's 1995. I'm seeing Hackers, for the first time, in the theatre. The opening song is Halcyon + On + On. I think, "Ok, Orbital, cool! A little old school. But I see what you're doing here. I'll allow it."

Anyway, if you see your mom this weekend, be sure and tell her...

Posted Fri Dec 7 11:06:02 2018 Tags:

Planet Debian upstream is hosted by Branchable.