{"id":74,"date":"2009-12-05T16:24:29","date_gmt":"2009-12-06T00:24:29","guid":{"rendered":"http:\/\/intr.overt.org\/blog\/?p=74"},"modified":"2009-12-05T16:24:29","modified_gmt":"2009-12-06T00:24:29","slug":"controlling-bluetooth-dun-with-upstart-on-the-n900","status":"publish","type":"post","link":"https:\/\/blog.intr.overt.org\/?p=74","title":{"rendered":"Controlling Bluetooth DUN with upstart on the n900"},"content":{"rendered":"<p>Wow, it&#8217;s been a long time since I posted anything. But I&#8217;ve got something worth coming out of hibernation for.<\/p>\n<p>Perhaps, unsurprisingly, I got myself an n900 and it&#8217;s a great device; I&#8217;m using it as my primary phone and it really is impressive.<\/p>\n<p>One thing that doesn&#8217;t work out of the box is DUN (Dial-Up Networking) over Bluetooth. DUN is one of the simplest ways to tether a computer to a phone, so it&#8217;s a useful feature to have. (The n900 does support DUN over USB by default). Fortunately, it&#8217;s very easy to turn on, as documented on the <a href=\"http:\/\/wiki.maemo.org\/index.php?title=Fremantle_Unsupported_Bluetooth_profiles#DUN_server\">maemo wiki<\/a>. However, if you want the feature to always be ready to go (say, after you restart your phone), you need to do a little more.<\/p>\n<p>Like modern versions of Ubuntu, the n900 with Maemo 5 uses <a href=\"http:\/\/upstart.ubuntu.com\/\">upstart<\/a> to control most startup services, such as bluetooth. So, if we want the DUN service to be nicely coordinated, we should start it with upstart too. Here&#8217;s my script:<\/p>\n<blockquote><p><code><br \/>\ndescription \"DUN over Bluetooth\"<br \/>\nauthor \"Philip Langdale\"<\/p>\n<p>respawn<br \/>\nconsole none<\/p>\n<p>start on started bluetoothd<br \/>\nstop on stopping bluetoothd<\/p>\n<p>pre-start script<br \/>\n        sdptool add --channel 1 DUN<br \/>\nend script<\/p>\n<p>exec rfcomm -S -- listen -1 1 \/usr\/bin\/pnatd '{}'<\/p>\n<p>post-stop script<br \/>\n        sdptool del `sdptool browse local | grep Dial-Up -A 1 -m 1 | tail -n 1 | cut -d ' ' -f 3`<br \/>\n        sleep 1<br \/>\nend script<br \/>\n<\/code><\/p><\/blockquote>\n<p>So, what is this doing? As upstart is pretty new, and quite different from old style init-scripts, it&#8217;s worth explaining a bit.<\/p>\n<p>The <i>description<\/i> and <i>author<\/i> fields are just for documentation. <i>respawn<\/i> means to restart if the main process exits. <i>console none<\/i> means don&#8217;t log stdout or stderr anywhere. <\/p>\n<p>Now, the <i>start on<\/i> and <i>stop on<\/i> directives are the heart of Upstart. They allow you to express dependencies between services, events, and each other. In this case, we want to start the DUN server after bluetoothd is started and stop it as soon as we start stopping bluetoothd. You can express multiple start and stop conditions and the upstart site documents these.<\/p>\n<p>With that done, we can move on to the functional code. From the wiki page, we see that the invocation of <i>rfcomm<\/i> is the key call. What happens here is rfcomm will wait for an incoming connectio request on channel 1 and then spawn <i>pnatd<\/i> and connect it to that channel. When the connection is complete, <i>pnatd<\/i> will exit and then <i>rfcomm<\/i> will too. Upstart either tracks a particular binary or a script. In either case, it <i>exec<\/i>s the binary or script and watches the resulting process to see when it exits. So, we can conveniently transfer the <i>rfcomm<\/i> command line to an upstart <i>exec<\/i> directive.<\/p>\n<p>However, there&#8217;s more to do. We have to register the service with <i>sdpd<\/i> so that clients know we offer DUN, and we have to unregister when the service is terminated. This can be done with the <i>pre-start<\/i> and <i>post-stop<\/i> blocks. This also gives us a place to enforce the one second delay suggested by the example script.<\/p>\n<p>Registering the service is easy, but unregistering it is a bit of a chore. The example script can avoid it because it uses the while loop, but for upstart, the entire service is &#8216;inside&#8217; the loop, so we must unregister to avoid adding an extra registration each time. The problem arises because you can only unregister by the service record ID which is selected at registration time, but not provided back to us. So, we must look for it ourselves. The long command line searches the list of services for DUN and then extracts the ID.<\/p>\n<p>Now, all you have to do is drop the script into <code>\/etc\/event.d\/<\/code> and then execute <code>start bluetooth-dun<\/code>, assuming you name the script &#8220;bluetooth-dun&#8221;. Obviously, you must be root for both these steps.<\/p>\n<p>You can download the script from <a href=\"http:\/\/intr.overt.org\/misc\/bluetooth-dun\">here<\/a>. I&#8217;ll probably package it up as a deb in due course, but I don&#8217;t have a working scratchbox environment right now.<\/p>\n<p>Enjoy!<\/p>\n<p><strong>Update:<\/strong> It seems that it&#8217;s not perfect yet. I&#8217;ve had a report, and reproduced, it failing to start when the phone boots, even though it starts reliably if you stop\/start bluetoothd. My suspicion is that there&#8217;s an additional dependency (maybe the rfcomm kernel module) that needs to be accounted for. I will investigate.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Wow, it&#8217;s been a long time since I posted anything. But I&#8217;ve got something worth coming out of hibernation for. Perhaps, unsurprisingly, I got myself an n900 and it&#8217;s a great device; I&#8217;m using it as my primary phone and it really is impressive. One thing that doesn&#8217;t work out of the box is DUN [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-74","post","type-post","status-publish","format-standard","hentry","category-maemo"],"_links":{"self":[{"href":"https:\/\/blog.intr.overt.org\/index.php?rest_route=\/wp\/v2\/posts\/74"}],"collection":[{"href":"https:\/\/blog.intr.overt.org\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.intr.overt.org\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.intr.overt.org\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.intr.overt.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=74"}],"version-history":[{"count":0,"href":"https:\/\/blog.intr.overt.org\/index.php?rest_route=\/wp\/v2\/posts\/74\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.intr.overt.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=74"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.intr.overt.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=74"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.intr.overt.org\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=74"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}