You can save bandwidth by pre-compressing your JavaScript files with gzip without relying on dynamic compression such as mod_deflate.  To to this properly and having it working across all browsers you’ll need to modify your webserver to return the correct mime type and encoding for the file.

Most browsers are quite liberal in what they accept, except for Safari/Konqueror. For some reason it doesn’t like it if a JavaScript file ends in .gz, it ignores the content-encoding and attempts to read the compressed data as JavaScript. The key to make it work is to create a new extension, for example .jgz and set the Content-Encoding for this extension to gzip AND to set the mime type of .js to text/javascript, not text/plain or application/x-javascript.

To recap, call the file script.js.jgz and make sure your webserver delivers it with the following options

Content-Encoding: gzip
Content-Type: text/javascript

Just include the file as usual

<script type="text/javascript" src="script.js.jgz"></script>

This has been tested with the following browsers

  • Firefox 3.0/3.5
  • Opera 10
  • Internet Explorer 7
  • Konqueror (webkit based, behaves like Safari)
  • Google Chrome 3
  • Epiphany

Apache

Put the following in a .htaccess file

AddType text/javascript .js
AddEncoding gzip .jsz

thttpd

Add jsz gzip to mime_encodings.txt and change the type for js in mime_types.txt to js text/javascript.

Comments Comments Off

VirtualBox (host mode) was quite recently ported to FreeBSD, some bits are still missing particular network support. So I spent the last couple of days hacking on it and how have a working implementation that supports bridged adapters.

Update 10 Sep: The patches have been committed upstreams.
Update 9 Sep: working vboxnetadp and patchset sent upstreams.
Update: Re-written to use netgraph, now works on FreeBSD 7 and 8

Patches can be found at

http://www.shapeshifter.se/pub/patches/virtualbox/vbox-freebsd-netif-20090908.patch
http://www.shapeshifter.se/pub/patches/virtualbox/vbox-freebsd-vboxnetadp-20090908.patch
http://www.shapeshifter.se/pub/patches/virtualbox/vbox-freebsd-vboxnetflt-20090908.patch
http://www.shapeshifter.se/pub/patches/virtualbox/Config.kmk-20090908.patch
http://www.shapeshifter.se/pub/patches/virtualbox/src-VBox-HostDrivers-Makefile.kmk-20090908.patch

Additional patches to test with the 3.0.51.r22226 version in FreeBSD ports.

http://www.shapeshifter.se/pub/patches/virtualbox/Config.kmk-r22226-20090908.patch
http://www.shapeshifter.se/pub/patches/virtualbox/virtualbox-port-20090907.patch
http://www.shapeshifter.se/pub/patches/virtualbox/ConsoleImpl2.cpp.patch

Re-install VirtualBox through ports using the following commands

Apply/compile with
cd /usr/ports/emulators/virtualbox
make clean patch
mkdir work/virtualbox-3.0.51r22226/src/VBox/HostDrivers/VBoxNetFlt/freebsd
mkdir work/virtualbox-3.0.51r22226/src/VBox/HostDrivers/VBoxNetAdp/freebsd
patch < virtualbox-port-20090907.patch
patch -d work/virtualbox-3.0.51r22226/Config.kmk-r22226-20090908.patch
patch -d work/virtualbox-3.0.51r22226/ConsoleImpl2.cpp.patch
patch -d work/virtualbox-3.0.51r22226/src-VBox-HostDrivers-Makefile.kmk-20090908.patch
patch -d work/virtualbox-3.0.51r22226/vbox-freebsd-netif-20090908.patch
patch -d work/virtualbox-3.0.51r22226/vbox-freebsd-vboxnetadp-20090908.patch
patch -d work/virtualbox-3.0.51r22226/vbox-freebsd-vboxnetflt-20090908.patch
make install

In VirtualBox network settings, under "Bridged Adapter" you should now see your available network interfaces. Select the one connected to your network and boot your virtual machine. It should now be connected to your local network as any other machine.

Host only adapter mode can be used to create a virtual network with multiple guests, it creates a special vboxnetX adapter on the host. You'll have to do normal routing between this interface to get outside connectivity.

In addition to vboxdrv.ko you'll have to load vboxnetflt.ko and vboxnetadp.ko too.

kldload /boot/modules/vboxnetflt.ko
kldload /boot/modules/vboxnetadp.ko

Comments 3 Comments »

A bit late, but here is the first beta of the Option HSDPA driver for FreeBSD 8. It’s more or less completely rewritten and there are some visible changes to the interface.

Because ucom(4) has matured it can now be utilized instead of mucking around directly with the TTY layer. This results in that the device names in /dev has changed and are now longer called /dev/HSO*, instead they follow the standard ucom names of cuaU*.

The new USB stack attach USB devices per USB interface instead of per USB device, so it’s possible to get both a cuaU0 and cuaU1 device (instead of just cuaU0.0 and cuaU0.1). The number of found serial ports can be read through sysctl.

The packet interface is now exposed as a raw interface instead of emulating an Ethernet device (I seriously wonder why I did that…).

The driver switches automatically from install-cd mode to modem mode, there is no longer any need for manual switching through devd. Please remove the option-icon.conf file from your /usr/local/etc/devd directory.
This can be disabled by setting hw.usb.uhso.auto_switch to 0

And last, I’ve renamed the driver to uhso to reflect its USB nature.

Download: uhso-20091122.tar.gz – Add support for iCON 505, fix probing of devices with dynamic number of interfaces, add new custom attach messages based on the port type.

Download: uhsoctl-beta-20090820.tar.gz – uhsoctl connection utility, similar to old hsoctl

Download: uhso-beta-20090812.tar.gz – Minor bug fix and reworked sysctl nodes.

Download: uhso-beta-20090723.tar.gz – No longer PTP interface (completely useless), fixed (hopefully) CDC notification on modem port, added several new device IDs. Thanks to Iain Hibbert for this!

Download: uhso-beta-20090722.tar.gz – Bug fixes that should improve RX speed.

Download: uhso-beta-20090720.tar.gz

If you own an Option device, please leave a comment (or send a mail) with its full name and USB device ID.

I’m particularly interested in the following devices iCON 031, iCON 210, iCON 315, iCON 322, iCON 401, iCON 431, iCON 451, iCON 452, iCON 505.

If you’re running FreeBSD 8 and own an Option device, please mail me the output of

usbconfig -u X -a Y dump_device_desc
usbconfig -u X -a Y dump_all_config_desc

where X and Y (5 and 2 below) can be obtained through usbconfig

# usbconfig
...
ugen5.2: <Globetrotter HSDPA Modem Option N.V.> at usbus5, cfg=0 md=HOST spd=FULL (12Mbps) pwr=ON

This driver has been tested with a Globesurfer iCON 7.2, iCON 255, iCON 505

Quick setup for manual connection
uhsoctl works as before!

Look up the serial ports

# sysctl dev.uhso
dev.uhso.0.netif: uhso0
dev.uhso.0.type: Network/Serial
dev.uhso.0.ports: 2
dev.uhso.0.port.control.tty: cuaU0.0
dev.uhso.0.port.control.desc: Control
dev.uhso.0.port.application.tty: cuaU0.1
dev.uhso.0.port.application.desc: Application
...
dev.uhso.1.type: Serial
dev.uhso.1.ports: 1
dev.uhso.1.port.diagnostic.tty: cuaU1
dev.uhso.1.port.diagnostic.desc: Diagnostic

Open /dev/cuaU0.0 in a terminal application, for example minicom. Issue the following commands to establish a connection.

AT+CPIN="1234" # Your PIN
OK

AT_OWANCALL=1,1,1
OK

AT_OWANDATA=1
_OWANDATA: 1, 95.209.79.126, 0.0.0.0, 80.251.201.177, 80.251.201.178, 0.0.0.0, 0.0.0.0, 72000

If you haven’t configured a PDP context with your providers APN, please see the hso page.

Configure the interface and set a default route

# ifconfig uhso0 95.209.79.126
# route add default -interface uhso0

Comments 15 Comments »

A project I’ve been hacking on for a while is a self-contained 1-wire to IPv6 bridge based on an Atmel AVR ATmega644 and the ENC28J60 Ethernet controller from Microchip.

1-wire: is a serial bus from Dallas Semiconductor/Maxim that only requires 1 data line, there are a number of cheap sensors and other devices for this bus. The strength of this bus is not its speed but that it supports large ranges (up to 300 meters).
Also, each 1-wire device has a permanent unique 64-bit serial number.

IPv6: Insanely large address space. It’s common to use a 64-bit netmask for site networks so that EUI-64 based addresses can be used for auto configuration. This leaves 64-bit for the node address – do you see where this is going now… :)

Yes..I’ve built a device that assigned each 1-wire device it’s connected to its own IPv6 address. Why? you ask, mostly because I can.

Hardware

As mentioned above, the device is based on an AVR ATmega644. It has 64KB of flash memory for program code and 4KB of RAM. It’s running on its built-in oscillator at 8MHz. The ENC28J60 Ethernet chip is connected to the AVR using SPI. The rest of the hardware is mostly for power distribution and management.

The PCB was manufactured by BatchPCB, cheap service but a bit slow turn-around time.

Populated PCB

Unfortunately I screwed up the SPI connection but I managed to fix that with some green wires (or black wires in this case). You’ll note them in the picture above.
I also intended to run the AVR at 5V and the ethernet chip at 3.3V. This is what the quad AND-gate in the upper right
corner was for, but since I screwed up the SPI routing it’s disconnected and the whole circuit is running at 3.3V.
The ENC28J60 can only run at 3.3V, the AVR has a range from 2.8-5V and 1-wire should be ran at 5V but works at 3.3V. Hence the need for TTL voltage translation.

As for the 1-wire devices I had implemented a bus master in software that generated the require waveforms. It worked great up to about 10-15 meters. Any cable length greater than that refused to work.
This was a bit unexpected and without an oscilloscope it was more or less impossible to figure out where and how the signals got mangled. So I simply got a DS2480 1-wire line driver that generates the required signals in hardware with more precise timing.

Add-on board with a 1-wire master

Add-on board with a 1-wire master

This required an add-on board and because I didn’t want to wait for a new PCB I used a 2.54mm prototype board. With the DS2480 only available in SOIC8 packages it required some “creative” soldering :).
The DS2480 required 5V, thus It had to get its own power supply and also required level translation on the UART line between this device and the AVR. I choose an approach using MOSFETs and a few resistors for this (the TO92 packages in the picture above). This turned out to work really good and I think I’m going to use this for the SPI level translation in the next revision of the board.
The wire leaving the board on the left side leads to the 1-wire sensor devices.

The add-on board is extremely ugly. But hey, it works.

Future improvements for the next revision

  • Use of external crystal at 16MHz instead of internal 8MHz clock.
  • Use MOSFETs for 3.3-5 V translation. Need to test it at 16MHz before manufacturing a PCB though.
  • Obviously fix all PCB errors :)
  • All SMD parts (resistors and voltage regulators) to shrink PCB size even more.
  • Better power distribution. I was a bit too conservative with the decoupling capacitors resulting in some weird power problems (fixable with some caps)
  • Create a real add-on board

I’ll publish the PCB CAD files when the next revision is complete.

Software

The only small IPv6 stack I know of is the uIPv6 stack in the Contiki operating system created by Adam Dunkel et al. This is unfortunately only available together with Contiki and not as a stand alone package as the originally uIP (IPv4) stack.

Contiki is a great operating system, but when you only have 4KB of RAM it becomes a bit heavy weight. So I broke out the uIPv6 stack from Contiki and made it run stand alone and ported in to AVR. I also ported the web server application from Contiki and made it run on AVR. As I wanted to use multiple IPv6 addresses I also had to add support for IP aliases to the uIPv6 stack.

Since the uIPv6 was integrated with Contiki it used the Contiki process model which it self is based on “proto-threads” (another thing invented by Adam Dunkel). I felt that this didn’t fit so I turned all processes into a polling mode instead. So one has to call a set of polling functions from the main application loop or from timers.

The other major parts of the code are drivers for ENC28J60, DS2480 and DS1820.

Software
1-wire devices
30 second polling interval with auto-discovery of new devices.
Each device is assigned its own IPv6 address, requires a /64 network to be available.
Webserver
Integrated web server makes it possible to visit each address. An XML file with the latest sensor reading is returned. An “age timestamp” is also provided which makes it possible to determine how old the reading is.

Currently, with 5 1-wire devices connected it uses about 3KB of RAM.

In-action

I only have temperature sensors connected at the moment. If you happen to have an IPv6 capable connection you can access the sensors through a web browser.

2001:16d8:ffe5:002:2894:eaf6:100:0c7
2001:16d8:ffe5:002:28c1:b4f6:100:035
2001:16d8:ffe5:002:2809:aef6:100:0ca
2001:16d8:ffe5:002:28c5:a5f6:100:058
2001:16d8:ffe5:002:2813:caf6:100:050

(If you don’t have IPv6 you should get it, or you can view graphs based on the sensor values at lindberg.tl instead).

DSC00664 DSC00661

Comments 21 Comments »

Do you have a bunch of useless USB-to-PS/2 keyboard adapters laying around? Two of them make a great female-female USB adapter – If you need one that is. Here is how I made one.

usb_to_ps2_open

Carefully crack the case open using a knife. You can be quite rough at the PS/2 end of the casing as this part will be
removed anyway. Don’t destroy the USB side of the casing as this part will be reused for our adapter casing later on.

Once opened you should basically have a USB-connector connected to a PS/2 connector covered in hot glue/plastic wrapped in a thin-foil like material (for shielding). Remove the wrapping and cut away the PS/2 connector with a knife.

Now, carefully remove the remaining plastic. Don’t worry about the soldered wires but make sure that you don’t damage the pins on the USB connector. You should end up with something like this.

usb_to_ps2_stripped

Do the same with another USB-PS/2 adapter so that you basically end up with two USB connectors.
Bring out your soldering iron and de-solder the remaining wires from the connectors.

usb_to_ps2_two_stripped

Place the connectors back-to-back and turn one of them 180 degrees so that it becomes “up-side-down”. If you don’t do this you’ll end up connecting the pins in the wrong way.
To make the pins touch each other you’ll have to bend them roughly 30-45 degrees. Solder the pins together.

usb_to_ps2_soldered

Cut out a piece of wire and solder it to the casing off each connector. You can use the existing solder points used for the shielding/ground or create a new. Some flux will help a lot here.

usb_to_ps2_soldered_gnd_side

That’s it for the connector. Next up is to creating a new casing using the existing casings. Unfortunately I forgot to take pictures of this process.
Take on pair of the two cases, take one of the two pieces and place the USB-USB adapter inside it . Make a mark on the casing approximately in the middle of where the soldered pins meet.
Cut at this point and do the same for the same half of the other case. Just do a rough cut and file the pieces until the adapter fits. Once the bottom fits, do the same for the top part using the bottom pieces as a template.

Place it in the new casing and pour some hot glue over it to make it steady. Glue the top on and it’s complete.
usb_to_usb_half_assembled

USB-USB female adapter in action.
usb_to_usb_assembled

Will it be as good as a commercial adapter? probably not. Will it effect data transmission? probably (depending on how good the solder joints are). Cheaper than a commercial adapter? yep (assuming you already have the parts needed and don’t factor in the labor :))

Comments 6 Comments »