aboutsummaryrefslogtreecommitdiffstats
path: root/keyboards/acr60/acr60.c
blob: 8a76020e547bad8fa4d820b31ac0e5420962b0e4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include "acr60.h"
#include "led.h"

void matrix_init_kb(void) {
  // Keyboard start-up code goes here
  // Runs once when the firmware starts up
  matrix_init_user();
  led_init_ports();
};

void matrix_scan_kb(void) {
  // Looping keyboard code goes here
  // This runs every cycle (a lot)
  matrix_scan_user();
};

void led_init_ports(void) {
  // Set caps lock LED pin as output
  DDRB |= (1 << 2);
  // Default to off
  PORTB |= (1 << 2);
}

void led_set_kb(uint8_t usb_led) {
  // Code for caps lock LED as reported by the OS
  // Set this per keymap, instead of globally
  led_set_user(usb_led);
}
ffffc0; padding: 0 5px 0 5px; } .highlight .hll { background-color: #ffffcc } .highlight { background: #ffffff; } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
/*
 * ConnectBot: simple, powerful, open-source SSH client for Android
 * Copyright 2007 Kenny Root, Jeffrey Sharkey
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.connectbot.util;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Locale;

import org.connectbot.R;
import org.json.JSONObject;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
import android.util.Log;

/**
 * Helper class that checks for updates to this application. On construction, it
 * spawns a background thread that checks for any app updates. If available,
 * shows a dialog to the user, prompting them to visit Market for the upgrade.
 *
 * <b>Be sure to change the UPDATE_URL field before using this class.</b> Then
 * place a text file at that URL containing JSON data in the format:
 *
 * <code>{"versionCode": 110, "features": "Brand new interface with over
 * 9,000 improvements.", "target": "search?q=searchterms"}</code>
 *
 * Which should contain information about your newest version. The
 * <code>target</code> field is used to build an Intent that launches Market on
 * the device, simply be prefixing it with <code>market://</code>. If you know
 * your exact Market ID, you could use the value
 * <code>details?id=yourexactmarketid</code>
 *
 * If you're looking for an advanced version-checking system that offers more
 * customization, check out Veecheck: http://www.tomgibara.com/android/veecheck/
 *
 * @author jsharkey
 */
public final class UpdateHelper implements Runnable {

	public final static String TAG = "ConnectBot.UpdateHelper";
	public final static String UPDATE_URL = "http://connectbot.org/version";

	protected Context context;

	private String packageName, versionName;
	protected int versionCode;

	private String userAgent;

	/**
	 * Constructor will automatically spawn thread to check for updates.
	 * Recommended usage is <code>new UpdateHelper(this);</code> in the first
	 * onCreate() of your app.
	 */
	public UpdateHelper(Context context) {
		this.context = context;

		try {
			// read current version information about this package
			PackageManager manager = context.getPackageManager();
			PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0);
			this.packageName = info.packageName;
			this.versionCode = info.versionCode;
			this.versionName = info.versionName;

		} catch(Exception e) {
			Log.e(TAG, "Couldn't find package information in PackageManager", e);
			return;
		}

		// decide if we really need to check for update
		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);

		String frequency;
		try {
			frequency = prefs.getString(PreferenceConstants.UPDATE, PreferenceConstants.UPDATE_DAILY);
		} catch (ClassCastException cce) {
			// Hm, somehow we got a long in there in the previous upgrades.
			frequency = PreferenceConstants.UPDATE_DAILY;
			Editor editor = prefs.edit();
			editor.putString(PreferenceConstants.UPDATE, frequency);
			editor.commit();
		}
		long lastChecked = prefs.getLong(PreferenceConstants.LAST_CHECKED, 0);
		long now = (System.currentTimeMillis() / 1000);
		long passed = now - lastChecked;

		boolean shouldCheck = false;
		if (PreferenceConstants.UPDATE_DAILY.equals(frequency)) {
			shouldCheck = (passed > 60 * 60 * 24);
		} else if (PreferenceConstants.UPDATE_WEEKLY.equals(frequency)) {
			shouldCheck = (passed > 60 * 60 * 24 * 7);
		}

		// place version information in user-agent string to be used later
		userAgent = String.format("%s/%s (%d, freq=%s, lang=%s)",
				packageName, versionName, versionCode, frequency,
				Locale.getDefault().getLanguage());

		if(shouldCheck) {
			// spawn thread to check for update
			// Note that this class should be marked final because a thread is started in the constructor.
			Thread updateThread = new Thread(this);
			updateThread.setName("UpdateHelper");
			updateThread.start();

			// update our last-checked time
			Editor editor = prefs.edit();
			editor.putLong(PreferenceConstants.LAST_CHECKED, now);
			editor.commit();

		}

	}

	public void run() {
		try {
			// fetch and parse the version update information as json
			// pass information off to handler to create
			JSONObject json = new JSONObject(UpdateHelper.getUrl(UPDATE_URL, userAgent));
			Message.obtain(versionHandler, -1, json).sendToTarget();

		} catch(Exception e) {
			Log.e(TAG, "Problem while fetching/parsing update response", e);

		}
	}


	/**
	 * Handler that will parse the JSON response and show dialog to user if an
	 * update is available.
	 */
	private Handler versionHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {

			// make sure we are being passed a real json object
			if(!(msg.obj instanceof JSONObject)) return;
			JSONObject json = (JSONObject)msg.obj;

			// pull out version and target information from response
			final int versionCode = json.optInt("versionCode");
			final String features = json.optString("features");
			final String target = "market://" + json.optString("target");

			// skip if we're already good enough
			if(versionCode <= UpdateHelper.this.versionCode) return;

			// build dialog to prompt user about updating
			new AlertDialog.Builder(context)
				.setTitle(R.string.upgrade)
				.setMessage(features)
				.setPositiveButton(R.string.upgrade_pos, new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(target));
						context.startActivity(intent);
					}
				})
				.setNegativeButton(R.string.upgrade_neg, null).create().show();

		}


	};

	/**
	 * Read contents of a URL and return as a String. Handles any server
	 * downtime with a 6-second timeout.
	 */
	private static String getUrl(String tryUrl, String userAgent) throws Exception {

		URL url = new URL(tryUrl);
		URLConnection connection = url.openConnection();
		connection.setConnectTimeout(6000);
		connection.setReadTimeout(6000);
		connection.setRequestProperty("User-Agent", userAgent);
		connection.connect();

		InputStream is = connection.getInputStream();
		ByteArrayOutputStream os = new ByteArrayOutputStream();

		int bytesRead;
		byte[] buffer = new byte[1024];
		while ((bytesRead = is.read(buffer)) != -1) {
			os.write(buffer, 0, bytesRead);
		}

		os.flush();
		os.close();
		is.close();

		return new String(os.toByteArray());

	}


}