<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Will Scott &#187; programming</title>
	<atom:link href="http://willscott.name/tag/programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://willscott.name</link>
	<description>Achievement Unlocked</description>
	<lastBuildDate>Sat, 24 Mar 2012 19:39:04 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Distributed Computing so far</title>
		<link>http://willscott.name/534/distributed-computing-so-far/</link>
		<comments>http://willscott.name/534/distributed-computing-so-far/#comments</comments>
		<pubDate>Mon, 12 Apr 2010 01:30:13 +0000</pubDate>
		<dc:creator>Will</dc:creator>
				<category><![CDATA[DistributedComputing]]></category>
		<category><![CDATA[distributed]]></category>
		<category><![CDATA[online]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://willscott.name/?p=534</guid>
		<description><![CDATA[I gave a half-hour presentation on my research at the admitted students weekend earlier.  I think I was able to convey some sense of the opportunities that Mudd offers for research, and presented a reasonable face of what it could look like. The talk was an explanation of the concepts behind distributed hash tables, and [...]]]></description>
			<content:encoded><![CDATA[<p>I gave a half-hour presentation on my research at the admitted students weekend earlier.  I think I was able to convey some sense of the opportunities that Mudd offers for research, and presented a reasonable face of what it could look like.</p>
<p>The talk was an explanation of the concepts behind distributed hash tables, and an introduction to the work I&#8217;ve been doing with bitTorrent.</p>
<p>These are the slides I used: <a href="http://willscott.name/wp-content/uploads/2010/04/ASP_presentation.pdf">Admitted Students presentation</a></p>
]]></content:encoded>
			<wfw:commentRss>http://willscott.name/534/distributed-computing-so-far/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Experiments in Data Moshing</title>
		<link>http://willscott.name/522/experiments-in-data-moshing/</link>
		<comments>http://willscott.name/522/experiments-in-data-moshing/#comments</comments>
		<pubDate>Thu, 08 Apr 2010 16:30:57 +0000</pubDate>
		<dc:creator>Will</dc:creator>
				<category><![CDATA[online]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://willscott.name/?p=522</guid>
		<description><![CDATA[Some work I&#8217;ve been doing for my experimental animation class.]]></description>
			<content:encoded><![CDATA[<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="350" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="src" value="http://www.youtube.com/v/FitcZWJwczQ" /><embed type="application/x-shockwave-flash" width="425" height="350" src="http://www.youtube.com/v/FitcZWJwczQ"></embed></object></p>
<p>Some work I&#8217;ve been doing for my experimental animation class.</p>
]]></content:encoded>
			<wfw:commentRss>http://willscott.name/522/experiments-in-data-moshing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Downloading Torrents</title>
		<link>http://willscott.name/399/downloading-torrents/</link>
		<comments>http://willscott.name/399/downloading-torrents/#comments</comments>
		<pubDate>Mon, 22 Feb 2010 22:02:10 +0000</pubDate>
		<dc:creator>Will</dc:creator>
				<category><![CDATA[DistributedComputing]]></category>
		<category><![CDATA[distributed]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://willscott.name/?p=399</guid>
		<description><![CDATA[I extended the work from last week in order to actually get data from a swarm. The main change is that new sockets are now allocated for each connection, state is remembered, and the client can actually get so far as to download data from the other peers. What needs to happen still is that [...]]]></description>
			<content:encoded><![CDATA[<p>I extended the work from last week in order to actually get data from a swarm.  The main change is that new sockets are now allocated for each connection, state is remembered, and the client can actually get so far as to download data from the other peers.</p>
<p>What needs to happen still is that 1. I need a better way of stopping, right now it stops upon a lull in network activity, but that doesn&#8217;t really mean anything.  2. I need to actually save downloaded data somewhere, or alternatively keep track of the rate that it&#8217;s coming in (or the time delay between packets.)  3. I need to factor out the different message types into separate modules to keep the code readable.</p>
<p>I&#8217;m going to set up a code page for this project soon, so that I don&#8217;t have to post stuff just in this blog.  I should get to that in the coming week, so that there&#8217;s a nicer way of interacting with this code base.  This model isn&#8217;t super memory efficient, but it is a very simple system to work with, and I think it&#8217;s become a good jumping off point for trying to interact with swarms.  In particular it&#8217;s really easy to add in hooks to get methods to run when messages are received, and to store arbitrary state about connections.</p>
<p>[python]<br />
# Standalone Torrent Auditor<br />
#<br />
import socket<br />
import time<br />
import sys<br />
import getopt<br />
import random<br />
import benc<br />
import binascii<br />
import select<br />
import hashlib<br />
import urllib<br />
import server</p>
<p>#a bit of global state about who we are<br />
client = &quot;AZ&quot;+chr(0&#215;05)+&quot;31&quot;<br />
myID = &quot;&quot;.join(chr(random.randrange(0, 256)) for i in xrange(20))<br />
peerCache=[]</p>
<p>#load in a .torrent file<br />
def readFile(filePath):<br />
	f = open(filePath, &#8216;r&#8217;)<br />
	data = &#8221;.join(f.readlines())<br />
	f.close()<br />
	return benc.bdecode(data)</p>
<p>#register with the tracker to generate potential peers<br />
def register(torrent,myPort):<br />
	url = torrent['announce'];<br />
	ihash = hashlib.sha1(benc.bencode(torrent['info'])).digest();<br />
	query = urllib.urlencode({&#8216;info_hash&#8217;:ihash,<br />
					&#8216;peer_id&#8217;:myID,<br />
					&#8216;port&#8217;:myPort,<br />
					&#8216;uploaded&#8217;:0,<br />
					&#8216;downloaded&#8217;:0,<br />
					&#8216;left&#8217;:0,<br />
					&#8216;compact&#8217;:1,<br />
					&#8216;event&#8217;:'started&#8217;});<br />
	url += &quot;?&quot;+query;<br />
	trackerhandle = urllib.urlopen(url);<br />
	trackerdata = &#8221;.join(trackerhandle.readlines());<br />
	trackerhandle.close();<br />
	parseddata = benc.bdecode(trackerdata);<br />
	initialnodes = parseddata['peers'];<br />
	peers = [];<br />
	while len(initialnodes) &gt; 5:<br />
		ip = initialnodes[0:4];<br />
		port = initialnodes[4:6];<br />
		initialnodes = initialnodes[6:];<br />
		peers.append({&#8216;state&#8217;:0,<br />
					   &#8216;ip&#8217;:socket.inet_ntoa(ip),<br />
					   &#8216;ihash&#8217;:ihash,<br />
					   &#8216;port&#8217;:ord(port[0])*256+ord(port[1]),<br />
					   &#8216;buffer&#8217;:&#8221;,<br />
					   &#8216;callback&#8217;:handleData});<br />
	return peers;</p>
<p>#register a new incoming connection<br />
def onNew(socket,(ip,port)):<br />
	obj = {&#8216;socket&#8217;:socket,<br />
			&#8216;ip&#8217;:ip,<br />
			&#8216;port&#8217;:port,<br />
			&#8216;state&#8217;:1,<br />
			&#8216;buffer&#8217;:&#8221;,<br />
			&#8216;callback&#8217;:handleData};<br />
	handleData(obj)<br />
	server.track_socket(obj);</p>
<p>#reply to a socket with a torrent message<br />
def reply(socket,mtype,payload):<br />
	#first flatten the payload<br />
	s = &#8221;;<br />
	while len(payload):<br />
		p = payload.pop();<br />
		if isinstance(p,int):<br />
			s += struct.pack(&#8216;!i&#8217;,p)<br />
		else:<br />
			s += p<br />
	s = chr(mtype) + s;<br />
	l = len(s);<br />
	pl = struct.pack(&#8216;!i&#8217;,l) + s;<br />
	socket.sendall(ppl);<br />
	return pl;</p>
<p>#parse torrent msg<br />
def handleMsg(obj,msg):<br />
	if msg[0] == 0: #choke<br />
		obj['state'] &amp;= ~4<br />
	elif msg[0] == 1: #unchoke<br />
		obj['state'] |= 4<br />
		#and we&#8217;d like to request a piece from them.<br />
		reply(obj['socket'],6,[0,0,2&lt;&lt;15])<br />
	elif msg[0] == 2: #interested<br />
		obj['state'] |= 8<br />
	elif msg[0] == 3: #uninterested<br />
		obj['state'] &amp;= ~8<br />
	elif msg[0] == 4: #have<br />
		idx = struct.unpack(&#8216;!i&#8217;,msg[1:5])<br />
		obj['have'][idx/8] |= (1 &lt;&lt; (8 &#8211; (idx%8)))<br />
	elif msg[0] == 5: #bitfield<br />
		obj['have'] = msg[1:]<br />
	elif msg[0] == 6: #request<br />
		#ignored<br />
		return;<br />
	elif msg[0] == 7: #piece<br />
		#got our data<br />
		print &quot;succeeded in downloading!&quot;<br />
	elif msg[0] == 8: #cancel<br />
		#we aren&#8217;t in that business<br />
		return;<br />
#parse incoming data<br />
def handleData(obj):<br />
	try: nbuf = obj['socket'].recv(4096)<br />
	except socket.error, err:<br />
		print &quot;disconnected %s&quot; %obj['ip']<br />
		server.closed_socket(obj['socket'])<br />
		return;<br />
	if not nbuf:<br />
		print &quot;disconnected %s&quot; % obj['ip']<br />
		server.closed_socket(obj['socket'])<br />
		return;<br />
	data = obj['buffer'] + nbuf;<br />
	#Handshake<br />
	if obj['state'] &amp;2 == 0:<br />
		if data[0] == chr(19) and len(data) &gt;= 68:<br />
			obj['ihash'] = data[28:48]<br />
			obj['peerid'] = data[48:68]<br />
			obj['buffer'] = data[68:]<br />
			obj['state'] += 2<br />
			if obj['state'] &amp; 1== 0:<br />
				#we need to respond to the handshake<br />
				obj['socket'].sendall(handshake(obj['ihash']))<br />
				obj['state'] += 1<br />
			print &quot;shook hands with %s&quot; % obj['ip'];</p>
<p>	#all other messages are prefixed by their length<br />
	else:<br />
		mlen = struct.unpack(&#8216;!i&#8217;,data[0:4])[0]<br />
		while len(data) &gt; mlen:<br />
			msg = data[1:mlen+1]<br />
			data = data[mlen+1:]<br />
			if len(msg):<br />
				#Actual message received<br />
				handleMsg(obj,msg);<br />
			if len(data):<br />
				mlen = ord(data[0]);<br />
			else:<br />
				break;<br />
		#save the rest of the data<br />
		obj['buffer'] = data<br />
		print &quot;unknown message %s&quot;%data</p>
<p>#define the handhsake<br />
def handshake(ihash):<br />
	announce = chr(19) + &#8216;BitTorrent protocol&#8217;<br />
	announce += chr(0&#215;0)*8<br />
	announce += ihash<br />
	announce += myID<br />
	return announce</p>
<p>#talk with cached peers<br />
def onTimeout():<br />
	global peerCache;<br />
	inited = 0;<br />
	if len(peerCache) == 0:<br />
		return True;<br />
	for i in range(5):<br />
		if len(peerCache) == 0:<br />
			break;<br />
		obj = peerCache.pop()<br />
		obj = server.track_socket(obj)<br />
		if not obj:<br />
			continue;<br />
		obj['socket'].sendall(handshake(obj['ihash']))<br />
		obj['state'] &amp;= 1<br />
	return False;</p>
<p>def usage():<br />
	global peerCache;<br />
	print &quot;Usage:&quot;;<br />
	print &quot;client &#8211;file=loc.torrent&quot;;<br />
	print &quot;Will report on statistics for the desired torrent&quot;;</p>
<p>def main():<br />
	filePath = &quot;default.torrent&quot;;<br />
	try:<br />
		opts, args = getopt.getopt(sys.argv[1:], &quot;hf:&quot;, [&quot;help&quot;, &quot;file=&quot;])<br />
	except getopt.GetoptError, err:<br />
		# print help information and exit:<br />
		print str(err) # will print something like &quot;option -a not recognized&quot;;<br />
		usage();<br />
		sys.exit(2);<br />
	for o, a in opts:<br />
		if o in (&quot;-h&quot;, &quot;&#8211;help&quot;):<br />
			usage();<br />
			sys.exit();<br />
		elif o in (&quot;-f&quot;, &quot;&#8211;file&quot;):<br />
			filePath = a;<br />
		else:<br />
			assert False, &quot;unhandled option&quot;;<br />
	print &quot;Loading Info&#8230; &quot;,<br />
	info = readFile(filePath);<br />
	print &quot;okay&quot;;<br />
	port = 6886;<br />
	print &quot;Detecting Swarm&#8230; &quot;,<br />
	seeds = register(info,port);<br />
	print len(seeds), &quot; peers returned&quot;;<br />
	peerCache.extend(seeds);<br />
	print &quot;Entering Main Loop&quot;;<br />
	onTimeout();<br />
	server.main_loop(onTimeout,onNew,port);<br />
	print &quot;Finished Snapshot&quot;;</p>
<p>if __name__ == &quot;__main__&quot;:<br />
    main()<br />
[/python] </p>
]]></content:encoded>
			<wfw:commentRss>http://willscott.name/399/downloading-torrents/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The &#8220;Mainline Kademlia&#8221; protocol</title>
		<link>http://willscott.name/337/the-mainline-kademlia-protocol/</link>
		<comments>http://willscott.name/337/the-mainline-kademlia-protocol/#comments</comments>
		<pubDate>Mon, 08 Feb 2010 07:53:35 +0000</pubDate>
		<dc:creator>Will</dc:creator>
				<category><![CDATA[DistributedComputing]]></category>
		<category><![CDATA[distributed]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://willscott.name/?p=337</guid>
		<description><![CDATA[Kademlia is a description of the network interactions and rpc calls that can form a distributed hash table. Today, these kad based DHTs are one of the most common forms of distributed storage. However, since kademlia does not specify the application level protocol to make calls, it is instead implemented on top of existing application [...]]]></description>
			<content:encoded><![CDATA[<p>Kademlia is a description of the network interactions and rpc calls that can form a distributed hash table.  Today, these kad based DHTs are one of the most common forms of distributed storage.  However, since kademlia does not specify the application level protocol to make calls, it is instead implemented on top of existing application protocols, making many of the rings incompatible with each other.</p>
<p>I was interested specifically in the Kad ring that is used by the Mainline Bitorrent client.  This storage is used in practice as a distributed source of information about torrents, so that new peers can join a swarm even when there is no tracker present.  The ring is used by utorrent, the official bittorrent.com client, and the Vuze client with an optional plugin. (Vuze has a native DHT which is incompatible with other systems.)</p>
<p>Unsurprisingly, the protocol for this DHT is well advertised.  The reason is two-fold: first, the amount of space is limited, and it is hard for clients to tell between valid and invalid data, so you don&#8217;t want to allow arbitrary data into the DHT.  Secondly, the questionable legality of many torrents means that it is detrimental for a third party to have a means to easily monitor the swarm.<br />
<span id="more-337"></span></p>
<h2>The Protocol</h2>
<p>This DHT is described as a <a href="http://www.bittorrent.org/beps/bep_0005.html">Bittorrent BEP </a>.  There are three remote procedure calls that need to be implemented for the protocol, and a fourth (ping) that can be used to help with reliability</p>
<h3>ping</h3>
<p>ping is used simply to make sure that another host in your routing table is still alive.  this is sent out periodically, and in fact with quite rapid frequency to make sure that your view of the DHT ring is mostly correct.  The ping is made with your id in the ring, and is responded to with the remote hosts ID.</p>
<h3>find_node</h3>
<p>this is used to discover new hosts in the DHT my querying known nodes.  You specify a specific point on the ring, and the host will return the 8 closest hosts to that point that it knows.  You must recursively send this request to find the closest possible node to any given point, since that mirrors the mode used by new nodes to join the ring.</p>
<h3>get_peers</h3>
<p>This is the get request of the protocol.  You can ask a host for the data stored against a 20 byte key.  If it has data for that key it will return it, as well as a token which you can then use to modify that data.<br />
Data is stored in multiples of 26 bytes, where the first 20 represent a position on the ring, the next four are the IP4 address of that node and the final two are the port.  The claim is that these nodes may be active in the swarm with the requested 20byte key.</p>
<h3>announce_peer</h3>
<p>Using the token from a previous get_peers request, you can add your own 26 bytes of data to the table.</p>
<h2>Uses</h2>
<p>It turns out that you can use this data to store messages of around 1MB.  To do this, you choose a key for the message, find the closest node to that key, and then execute a string of alternating get_peers and announce_peer requests.  You would use the port number as an index for ordering of your messages, and the 20 byte index fields to store the actual data.  The primary problem is that recovery is not guaranteed.  Each get_peers request will return only a limited number of peers, and depending on the method used data will either be lost (all but the last few messages will be dropped from the DHT) or returned randomly.</p>
<p>A more sophisticated storage method could get around this problem.  My first inclination would be to set up a system which jumped keys fairly frequently, storing at most 4 to 8 messages in each key, and then a pointer to the next key.  This method would also remove the size limitation caused by the naive implementation but would be more susceptible to data loss issues.</p>
]]></content:encoded>
			<wfw:commentRss>http://willscott.name/337/the-mainline-kademlia-protocol/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The One-Day Website</title>
		<link>http://willscott.name/273/the-one-day-website/</link>
		<comments>http://willscott.name/273/the-one-day-website/#comments</comments>
		<pubDate>Wed, 06 Jan 2010 03:40:48 +0000</pubDate>
		<dc:creator>Will</dc:creator>
				<category><![CDATA[online]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://willscott.name/?p=273</guid>
		<description><![CDATA[I spent today building http://setTimeout.net, a website that I was inspired to create yesterday evening. I set myself the goal of finishing the project in one day, I&#8217;ve managed to get done enough in that time period, and I&#8217;m pretty happy with how it turned out. I came up with several ideas for how to [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://settimeout.net/logo.png" alt="SetTimeout Logo" class="alignleft"/><br />
I spent today building <a href="http://settimeout.net/">http://setTimeout.net</a>, a website that I was inspired to create yesterday evening.</p>
<p>I set myself the goal of finishing the project in one day, I&#8217;ve managed to get done enough in that time period, and I&#8217;m pretty happy with how it turned out.  I came up with several ideas for how to improve it in the process, namely letting you create a bookmark that immediately saved a page for a set duration without further interaction, and integration with twitter.</p>
<p>The goal of the site is to work like javascript&#8217;s setTimeout(); function.  You pass it a URL, and a time (in days), and the url will pop up in your news reader after the timeout expires.  It&#8217;s useful if you want to check on the status of a project, but it isn&#8217;t interesting enough to monitor constantly, or if you find an interesting website that isn&#8217;t loading.</p>
<p>It&#8217;s very minimal in a lot of ways, and that&#8217;s sort of the point.  It&#8217;s actually fairly easy to interface with: you give it data in one end, and when the timeout expires it spits them out as rss.  I&#8217;m considering spending another day at some point to allow it to push data when the timeout expires, or to provide alternative interfaces to the resulting pages.</p>
]]></content:encoded>
			<wfw:commentRss>http://willscott.name/273/the-one-day-website/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Launchpad Update</title>
		<link>http://willscott.name/261/launchpad-update/</link>
		<comments>http://willscott.name/261/launchpad-update/#comments</comments>
		<pubDate>Mon, 04 Jan 2010 01:36:16 +0000</pubDate>
		<dc:creator>Will</dc:creator>
				<category><![CDATA[online]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://willscott.name/?p=261</guid>
		<description><![CDATA[I am almost done rewriting my launchpad code so that it can be run without a kernel module. Instead, I&#8217;ll be using libusb, which is a reasonably common and cross-platform library for interacting with USB devices. I&#8217;m having a couple issues with callbacks and polling, but I&#8217;m making pretty steady progress, and should have a [...]]]></description>
			<content:encoded><![CDATA[<p>I am almost done rewriting my launchpad code so that it can be run without a kernel module.  Instead, I&#8217;ll be using libusb, which is a reasonably common and cross-platform library for interacting with USB devices.<br />
<br />
I&#8217;m having a couple issues with callbacks and polling, but I&#8217;m making pretty steady progress, and should have a stable version to post pretty soon.<br />
<br />
The header for interactions with the launchpad is going to look like this:<br />
<code><br />
typedef void(*launchpad_callback)(unsigned char* data, size_t len, void* user_data);<br />
<br />
struct launchpad_handle* launchpad_register(launchpad_callback e, void* user_data);<br />
<br />
int launchpad_write(struct launchpad_handle *dp, unsigned char* data, size_t len);<br />
int launchpad_poll(struct pollfd* descriptors, size_t num);<br />
<br />
void launchpad_deregister(struct launchpad_handle* dp);<br />
</code><br />
You start by writing your callback function, which will be called whenever new data is available from the launchpad, or a write to the launchpad completes.  Then register that to start receiving notifications.  Call write to send data to the device, and use the launchpad_poll in your main loop, which externally will act as a standard system <code>poll()</code> call, but also handles device events.<br />
<br />
It&#8217;s worth noting that you can play with the kernel module already by downloading the code from the <a href="http://code.google.com/p/launchpadd">project page </a><br />
<br />
On the technical side, I&#8217;ve worked through a couple issues that took a bit more debugging than I really wanted, so I figured I&#8217;d post them here:<br />
<br />
The correct formulation for <code>libusb_lock_events</code> appears to be put immediately before your call to <code>poll()</code>, and you should unlock immediately afterwards.  If you lock events for the entire access time, you will find that although you&#8217;re polling, the reads and writes you initiate never get processed.<br />
<br />
If <code>libusb_submit_transfer()</code> is failing with code -1, it&#8217;s possibly a IO error, meaning that you don&#8217;t have your endpoint correctly defined.  For me the issue was that although my output endpoint was an interrupt type, it actually was registered as a bulk-data type.  (that is, it&#8217;s address was <code>0x02</code> rather than <code>0x01</code>.  Checking your endpoints with <code>lsusb -v</code> will let you check what the actual endpoints should be.)</p>
]]></content:encoded>
			<wfw:commentRss>http://willscott.name/261/launchpad-update/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Novation Launchpad</title>
		<link>http://willscott.name/248/novation-launchpad/</link>
		<comments>http://willscott.name/248/novation-launchpad/#comments</comments>
		<pubDate>Mon, 28 Dec 2009 18:37:45 +0000</pubDate>
		<dc:creator>Will</dc:creator>
				<category><![CDATA[online]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[tech]]></category>

		<guid isPermaLink="false">http://willscott.name/?p=248</guid>
		<description><![CDATA[Information here is outdated. Look instead at the Latest Progress. The new toy I got for christmas was a novation Launchpad.  It&#8217;s a Midi controller developed specifically for ableton live, and is able to both generate midi data or trigger program actions. Since my current computer is running ubuntu, I was planning to use it [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_249" class="wp-caption alignleft" style="width: 610px"><a class="image-link" href="http://willscott.name/wp-content/uploads/2009/12/novation_launchpad-600x409.jpg"><img class="size-large wp-image-249 " title="Launchpad" src="http://willscott.name/wp-content/uploads/2009/12/novation_launchpad-600x409.jpg" alt="The Novation Launchpad" width="600" height="409" /></a><p class="wp-caption-text">Launchpad</p></div>
<p>Information here is outdated.  Look instead at the <a href="http://willscott.name/?s=launchpad">Latest Progress</a>. </p>
<p>The new toy I got for christmas was a <a href="http://us.novationmusic.com/products/midi_controller/launchpad">novation Launchpad</a>.  It&#8217;s a Midi controller developed specifically for ableton live, and is able to both generate midi data or trigger program actions.</p>
<p>Since my current computer is running ubuntu, I was planning to use it in that context, but the device uses its own protocol to communicate at the USB level.  Luckily, the protocol is not a difficult one, in that it is stateless, and consists entirely of sending specific 3-byte sequences to the device.  With that in mind, I started reading through documentation to figure out what it would take to develop a linux driver that was compatible with the protocol.</p>
<p>Two days later I have a reasonably stable kernel module, and a basic midi driver for the launchpad running under linux.  I&#8217;ve placed the work as a google code project, and it is available for perusal: <a href="http://code.google.com/p/launchpadd">http://code.google.com/p/launchpadd/</a></p>
<p>The coding was really interesting, since it was my first experience writing a kernel module.   The kernel environment has always scared me and perhaps rightly so, since I did cause several hard crashes while I was developing this code, but overall it was not unpleasant.  The device did almost everything I wanted using the skeleton USB driver provided in the kernel source, with the one exception that the included driver did not support polling for events.  Since I wanted to allow for non-blocking reads to the device I switched it&#8217;s queues so that it would properly hook up with the character device polling interface.</p>
<p>My eventual goal is to use the launchpad as a control device for my computer, showing and allowing for control of things like virtual desktop, volume, email, battery, and clipboards.  I&#8217;ve already written a couple of these functions, and hope to have it essentially finished by the end of winter break when I go back to school.  This has been one of the most fun programming projects I&#8217;ve undertaken in a while, since I get the excuse to write in several different contexts, and bring in several of the concepts like sockets and selecting that I got excited by in the fall.</p>
]]></content:encoded>
			<wfw:commentRss>http://willscott.name/248/novation-launchpad/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

