code:
---
title: Suppliers selling Libreboot pre-installed
...

Libiquity
---------

Patrick McDermott, Libiquity's founder, is a former Libreboot
developer. **Ships to USA only**

-   [Taurinus X200 laptop](https://shop.libiquity.com/product/taurinus-x200) (FSF RYF certified)
-   [Libreboot chassis](https://shop.libiquity.com/product/libreboot-stickers-shaped-matte-vinyl-2x2.25-3-pack) and [Libreboot Inside stickers](https://shop.libiquity.com/product/libreboot-inside-case-badges-3-pack)

Home page:
<https://shop.libiquity.com/>

Ministry of Freedom (Minifree)
------------------------------

Leah Rowe, Minifree's founder, is also Libreboot's founder and is an active
Libreboot developer. Minifree is the first company to achieve FSF RYF
endorsement on a computer system, and invests money directly into Libreboot.

**Minifree ships worldwide, to all countries.**

Routers:

-   [Libre WNDR3800 Router](https://minifree.org/product/minifree-wndr3800-libre-router/) (FSF RYF pending)

Laptops:

-   [Libreboot X200 Tablet laptop](https://minifree.org/product/libreboot-x200-tablet/) (FSF RYF certified)
-   [Libreboot X200 laptop](https://minifree.org/product/libreboot-x200/) (FSF RYF certified)
-   [Libreboot T400 laptop](https://minifree.org/product/libreboot-t400/) (FSF RYF certified)

Services:

-   [Libreboot installation service](https://minifree.org/product/libreboot-installation-service/)
-   [Libreboot chip flashing service for ASUS KGPE-D16 and KCMA-D8](https://minifree.org/product/d8-d16-chipflash/)

Merchandise:

-   [Libreboot T400 battery](https://minifree.org/product/libreboot-t400-battery/)
-   [Libreboot X200 battery](https://minifree.org/product/libreboot-x200-battery/)
-   [Libreboot X200 Tablet battery](https://minifree.org/product/libreboot-x200-tablet-battery/)
-   [Libreboot X200/X200T docking station](https://minifree.org/product/docking-station-for-libreboot-x200/)
-   [Libreboot stickers](https://minifree.org/product/libreboot-stickers/)

Home page:
<https://minifree.org/>

Phreedom 2600
------------------

Phreedom 2600 sells the BeagleBone Black (which can be used for flashing Libreboot)
and the Thinkpad X200. All computers come with Parabola GNU/Linux preinstalled.
All products meets the criteria for [Respects Your Freedom](https://fsf.org/ryf).

Home page:
<https://shop.phreedom2600.net/>

Raptor Engineering
------------------

Raptor is the world's first libre OEM, producing systems with libre boot
firmware and operating system preinstalled, *from the factory*.

Website for pre-orders:
<https://www.raptorcs.com/TALOSII/>

They have 2 systems available:

- [TALOS II Lite](https://secure.raptorcs.com/content/TL1BC1/purchase.html)
  (this is the cheaper version)
- [TALOS II](https://secure.raptorcs.com/content/TL2WK2/intro.html)

NOTE: this isn't technically Libreboot, but the boot firmware is entirely free.

This is the same company that ported the ASUS KFSN4-DRE, KGPE-D16 and KCMA-D8
mainboards to Libreboot. Raptor has also helped improve other ports in Libreboot,
for instance they added support for *switchable graphics* on the ThinkPad T400
which Libreboot supports.

Home page:
<https://www.raptorcs.com/>

Technoethical
-------------

Technoethical (formerly Tehnoetic) is a team of free software activists and
developers that are selling hardware pre-installed with libreboot as a way to
fund the activity within their nonprofit foundation.

**Ships worldwide, to all countries.**

Services:

-   [Libreboot installation service](https://tehnoetic.com/tet-lis)

Laptops:

-   [Technoethical T500 laptop](https://tehnoetic.com/tet-t500)
-   [Technoethical T400 laptop](https://tehnoetic.com/tet-t400)
-   [Technoethical T400S laptop](https://tehnoetic.com/tet-t400s)
-   [Technoethical X200 Tablet laptop](https://tehnoetic.com/tet-x200t)
-   [Technoethical X200 laptop](https://tehnoetic.com/tet-x200)

Home page:
<https://tehnoetic.com/>

Vikings
-------

Vikings is the first company to offer hosting on hardware pre-installed with
libreboot and they are also selling the hardware itself to fund the building
of their libreboot-powered datacenter.

**Ships worldwide, to all countries.**

Servers:

-   [Vikings D16 1U server](https://store.vikings.net/libre-friendly-hardware/the-server-1u)

Mainboards:

-   [Vikings D16 mainboard](https://store.vikings.net/libre-friendly-hardware/d16-ryf-certfied) (FSF RYF certified)

Desktops:

-   [Vikings D16 workstation](https://store.vikings.net/libre-friendly-hardware/vikings-d16-workstation)

Laptops:

-   [Vikings X200 laptop](https://store.vikings.net/libre-friendly-hardware/x200-ryf-certfied) (FSF RYF certified)

Home page:
<https://vikings.net/>

Other suppliers
===============

Sellers on eBay
---------------

On the eBay website, in various countries, you can search for libreboot and
you may find some individual sellers providing Libreboot-preinstalled hardware.

We cannot verify the quality of these suppliers, but they do exist.

Some of them also provide choice of GNU+Linux distribution, or they may provide
services where you can ship your Libreboot-compatible device to them and they
would install Libreboot for you.

This can be useful for some people, but due to the nature of eBay, we cannot
link to them since eBay listings are regularly deleted due to expiration (some
sellers may choose to have longer listings, or renew expired listings).

There may also be other websites similar to eBay (e.g. mercado livre, available
for several South American countries) that might have Libreboot hardware on
them.

**If you are considering purchasing from a supplier on eBay, make sure to read
their feedback comments for other products that they sell, and check their
seller rating. Don't get duped by a bad seller!**

Workshops/hackerspaces
----------------------

You may have a GNU+Linux User Group, free software workshop or hackerspace near
you that can help you with installing Libreboot, for instance.


code:
<!DOCTYPE html>

  <meta charset="utf-8">
  <meta name="generator" content="pandoc">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
$for(author-meta)$
  <meta name="author" content="$author-meta$">
$endfor$
$if(date-meta)$
  <meta name="dcterms.date" content="$date-meta$">
$endif$
$if(keywords)$
  <meta name="keywords" content="$for(keywords)$$keywords$$sep$, $endfor$">
$endif$
  <title>$if(title-prefix)$$title-prefix$ – $endif$$pagetitle$</title>
$if(quotes)$

$endif$
$if(highlighting-css)$

$endif$
$for(css)$
  <link rel="stylesheet" href="$css$">
$endfor$
$if(math)$
  $math$
$endif$
$for(header-includes)$
  $header-includes$
$endfor$
<link rel="alternate" type="application/rss+xml" title="RSS Feed" href="/feed.xml"/>

$for(include-before)$
$include-before$
$endfor$
$if(title)$

$title$

$if(subtitle)$

$subtitle$

$endif$
$for(author)$

$author$

$endfor$
$if(date)$

$date$

$endif$

$endif$
$if(return)$
$return$
$endif$
$if(toc)$

$toc$

$endif$
$body$
$for(include-after)$
$include-after$
$endfor$

license: mit


code:
*.cmd
*.ko
*.mod
*.mod.*
*.o
*.order
*.symvers

path: .gitignore

license: unknown


code:
# Notes:
# -----------
# This clever makefile was shamelessly copied from the ivtv project.
#
# By default, the build is done against the running kernel version.
# to build against a different kernel version, set KVER
#
#  make KVER=2.6.11-alpha
#
#  Alternatively, set KDIR
#
#  make KDIR=/usr/src/linux

V ?= 0
MDIR := extra
KVER ?= $(shell uname -r)
KDIR ?= /lib/modules/$(KVER)/build
FWDIR ?= /lib/firmware

obj-m	+= sny6001ux.o
sny6001ux-objs := sony-pic.o compat.o

all::
	$(MAKE) -C $(KDIR) M=$(CURDIR) V=$(V) modules

install:: all
	$(MAKE) INSTALL_MOD_PATH=$(DESTDIR) INSTALL_MOD_DIR=$(MDIR) \
		-C $(KDIR) M=$(CURDIR) modules_install
	/sbin/depmod -a

clean::
	$(MAKE) -C $(KDIR) M=$(CURDIR) clean
	rm -f Module.symvers

path: Makefile


code:
Linux driver for Sony Programmable IO Control - SPIC (SNY6001)

This driver has been modified to correctly report button presses on VGN-UX.

Please make sure the sony-laptop and sonypi modules are unloaded before loading this module.

The code is based on the sony-laptop driver.

path: README


code:
#include <linux/types.h>

#ifdef CONFIG_SONYPI_COMPAT
#include <linux/poll.h>
#include <linux/miscdevice.h>

/******** SONYPI compatibility **********/

static int minor = -1;
module_param(minor, int, 0);
MODULE_PARM_DESC(minor,
		 "minor number of the misc device for the SPIC compatibility code, "
		 "default is -1 (automatic)");

/* battery / brightness / temperature  addresses */
#define SONYPI_BAT_FLAGS	0x81
#define SONYPI_LCD_LIGHT	0x96
#define SONYPI_BAT1_PCTRM	0xa0
#define SONYPI_BAT1_LEFT	0xa2
#define SONYPI_BAT1_MAXRT	0xa4
#define SONYPI_BAT2_PCTRM	0xa8
#define SONYPI_BAT2_LEFT	0xaa
#define SONYPI_BAT2_MAXRT	0xac
#define SONYPI_BAT1_MAXTK	0xb0
#define SONYPI_BAT1_FULL	0xb2
#define SONYPI_BAT2_MAXTK	0xb8
#define SONYPI_BAT2_FULL	0xba
#define SONYPI_TEMP_STATUS	0xC1

/* get/set brightness */
#define SONYPI_IOCGBRT		_IOR('v', 0, __u8)
#define SONYPI_IOCSBRT		_IOW('v', 0, __u8)

/* get battery full capacity/remaining capacity */
#define SONYPI_IOCGBAT1CAP	_IOR('v', 2, __u16)
#define SONYPI_IOCGBAT1REM	_IOR('v', 3, __u16)
#define SONYPI_IOCGBAT2CAP	_IOR('v', 4, __u16)
#define SONYPI_IOCGBAT2REM	_IOR('v', 5, __u16)

/* get battery flags: battery1/battery2/ac adapter present */
#define SONYPI_BFLAGS_B1	0x01
#define SONYPI_BFLAGS_B2	0x02
#define SONYPI_BFLAGS_AC	0x04
#define SONYPI_IOCGBATFLAGS	_IOR('v', 7, __u8)

/* get/set bluetooth subsystem state on/off */
#define SONYPI_IOCGBLUE		_IOR('v', 8, __u8)
#define SONYPI_IOCSBLUE		_IOW('v', 9, __u8)

/* get/set fan state on/off */
#define SONYPI_IOCGFAN		_IOR('v', 10, __u8)
#define SONYPI_IOCSFAN		_IOW('v', 11, __u8)

/* get temperature (C) */
#define SONYPI_IOCGTEMP		_IOR('v', 12, __u8)

struct sonypi_compat_s {
	struct fasync_struct* fifo_async;
	struct kfifo          fifo;
	spinlock_t            fifo_lock;
	wait_queue_head_t     fifo_proc_list;
	atomic_t              open_count;
};
static struct sonypi_compat_s sonypi_compat = {
	.open_count = ATOMIC_INIT(0),
};

static int sonypi_misc_fasync(int fd, struct file *filp, int on){
	return fasync_helper(fd, filp, on, &sonypi_compat.fifo_async);
}

static int sonypi_misc_release(struct inode *inode, struct file *file){
	atomic_dec(&sonypi_compat.open_count);
	return 0;
}

static int sonypi_misc_open(struct inode *inode, struct file *file){
	/* Flush input queue on first open */
	unsigned long flags;
	spin_lock_irqsave(&sonypi_compat.fifo_lock, flags);
	if (atomic_inc_return(&sonypi_compat.open_count) == 1) kfifo_reset(&sonypi_compat.fifo);
	spin_unlock_irqrestore(&sonypi_compat.fifo_lock, flags);
	return 0;
}

static ssize_t sonypi_misc_read(struct file *file, char __user *buf, size_t count, loff_t *pos){
	ssize_t ret;
	unsigned char c;

	if( (kfifo_len(&sonypi_compat.fifo) == 0) && (file->f_flags & O_NONBLOCK) ) return -EAGAIN;

	ret = wait_event_interruptible( sonypi_compat.fifo_proc_list, kfifo_len(&sonypi_compat.fifo) != 0 );
	if( ret ) return ret;

	while (ret < count &&
	       (kfifo_out_locked(&sonypi_compat.fifo, &c, sizeof(c),
			  &sonypi_compat.fifo_lock) == sizeof(c))) {
		if( put_user(c, buf++) ) return -EFAULT;
		ret++;
	}

	if (ret > 0) {
		struct inode *inode = file_inode(file);
		inode->i_atime = current_time(inode);
	}

	return ret;
}

static __poll_t sonypi_misc_poll(struct file *file, poll_table *wait)
{
	poll_wait(file, &sonypi_compat.fifo_proc_list, wait);
	if (kfifo_len(&sonypi_compat.fifo))
		return EPOLLIN | EPOLLRDNORM;
	return 0;
}

static int ec_read16( u8 addr, u16 *value ){
	u8 val_lb, val_hb;
	if( ec_read(addr, &val_lb) ) return -1;
	if( ec_read(addr + 1, &val_hb) ) return -1;
	*value = val_lb | (val_hb << 8);
	return 0;
}

static long sonypi_misc_ioctl( struct file *fp, unsigned int cmd, unsigned long arg ){
	int ret = 0;
	void __user *argp = (void __user *)arg;
	u8 val8;
	u16 val16;
	int value;

	mutex_lock(&spic_dev.lock);
	switch(cmd){
		case SONYPI_IOCGBRT:
			if (sony_bl_props.dev == NULL) {
				ret = -EIO;
				break;
			}
			if (sony_nc_int_call(sony_nc_acpi_handle, "GBRT", NULL,
						&value)) {
				ret = -EIO;
				break;
			}
			val8 = ((value & 0xff) - 1) << 5;
			if (copy_to_user(argp, &val8, sizeof(val8)))
					ret = -EFAULT;
			break;
		case SONYPI_IOCSBRT:
			if (sony_bl_props.dev == NULL) {
				ret = -EIO;
				break;
			}
			if (copy_from_user(&val8, argp, sizeof(val8))) {
				ret = -EFAULT;
				break;
			}
			value = (val8 >> 5) + 1;
			if (sony_nc_int_call(sony_nc_acpi_handle, "SBRT", &value,
						NULL)) {
				ret = -EIO;
				break;
			}
			/* sync the backlight device status */
			sony_bl_props.dev->props.brightness =
				sony_backlight_get_brightness(sony_bl_props.dev);
			break;
		case SONYPI_IOCGBAT1CAP:
			if (ec_read16(SONYPI_BAT1_FULL, &val16)) {
				ret = -EIO;
				break;
			}
			if (copy_to_user(argp, &val16, sizeof(val16)))
				ret = -EFAULT;
			break;
		case SONYPI_IOCGBAT1REM:
			if (ec_read16(SONYPI_BAT1_LEFT, &val16)) {
				ret = -EIO;
				break;
			}
			if (copy_to_user(argp, &val16, sizeof(val16)))
				ret = -EFAULT;
			break;
		case SONYPI_IOCGBAT2CAP:
			if (ec_read16(SONYPI_BAT2_FULL, &val16)) {
				ret = -EIO;
				break;
			}
			if (copy_to_user(argp, &val16, sizeof(val16)))
				ret = -EFAULT;
			break;
		case SONYPI_IOCGBAT2REM:
			if (ec_read16(SONYPI_BAT2_LEFT, &val16)) {
				ret = -EIO;
				break;
			}
			if (copy_to_user(argp, &val16, sizeof(val16)))
				ret = -EFAULT;
			break;
		case SONYPI_IOCGBATFLAGS:
			if (ec_read(SONYPI_BAT_FLAGS, &val8)) {
				ret = -EIO;
				break;
			}
			val8 &= 0x07;
			if (copy_to_user(argp, &val8, sizeof(val8)))
				ret = -EFAULT;
			break;
		case SONYPI_IOCGBLUE:
			val8 = spic_dev.bluetooth_power;
			if (copy_to_user(argp, &val8, sizeof(val8)))
				ret = -EFAULT;
			break;
		case SONYPI_IOCSBLUE:
			if (copy_from_user(&val8, argp, sizeof(val8))) {
				ret = -EFAULT;
				break;
			}
			__sony_pic_set_bluetoothpower(val8);
			break;
		/* FAN Controls */
		case SONYPI_IOCGFAN:
			if (sony_pic_get_fanspeed(&val8)) {
				ret = -EIO;
				break;
			}
			if (copy_to_user(argp, &val8, sizeof(val8)))
				ret = -EFAULT;
			break;
		case SONYPI_IOCSFAN:
			if (copy_from_user(&val8, argp, sizeof(val8))) {
				ret = -EFAULT;
				break;
			}
			if (sony_pic_set_fanspeed(val8))
				ret = -EIO;
			break;
		/* GET Temperature (useful under APM) */
		case SONYPI_IOCGTEMP:
			if (ec_read(SONYPI_TEMP_STATUS, &val8)) {
				ret = -EIO;
				break;
			}
			if (copy_to_user(argp, &val8, sizeof(val8)))
				ret = -EFAULT;
			break;
		default:
			ret = -EINVAL;
	}
	mutex_unlock(&spic_dev.lock);
	return ret;
}

static const struct file_operations sonypi_misc_fops = {
	.owner          = THIS_MODULE,
	.read           = sonypi_misc_read,
	.poll           = sonypi_misc_poll,
	.open           = sonypi_misc_open,
	.release        = sonypi_misc_release,
	.fasync         = sonypi_misc_fasync,
	.unlocked_ioctl = sonypi_misc_ioctl,
	.llseek         = noop_llseek,
};

static struct miscdevice sonypi_misc_device = {
	.minor = MISC_DYNAMIC_MINOR,
	.name  = KBUILD_MODNAME,
	.fops  = &sonypi_misc_fops,
};

void sonypi_compat_report_event( u8 event ){
	kfifo_in_locked( &sonypi_compat.fifo, (unsigned char *)&event, sizeof(event), &sonypi_compat.fifo_lock );
	kill_fasync(&sonypi_compat.fifo_async, SIGIO, POLL_IN);
	wake_up_interruptible(&sonypi_compat.fifo_proc_list);
}

int sonypi_compat_init( void ){
	int error;

	spin_lock_init(&sonypi_compat.fifo_lock);
	error = kfifo_alloc( &sonypi_compat.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL );
	if( error ){
		pr_err("kfifo_alloc failed\n");
		return error;
	}

	init_waitqueue_head(&sonypi_compat.fifo_proc_list);

	if( minor != -1 ) sonypi_misc_device.minor = minor;
	error = misc_register(&sonypi_misc_device);
	if( error ){
		pr_err("misc_register failed\n");
		goto err_free_kfifo;
	}
	if( minor == -1 ) pr_info( "device allocated minor is %d\n", sonypi_misc_device.minor );

	return 0;

err_free_kfifo:
	kfifo_free(&sonypi_compat.fifo);
	return error;
}

void sonypi_compat_exit(void){
	misc_deregister(&sonypi_misc_device);
	kfifo_free(&sonypi_compat.fifo);
}
#else
int sonypi_compat_init(void) { return 0; }
void sonypi_compat_exit(void) { }
void sonypi_compat_report_event(u8 event) { }
#endif /* CONFIG_SONYPI_COMPAT */


code:
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * This comment was taken from the original sony-laptop code
 *
 * ACPI Sony Notebook Control Driver (SNC and SPIC)
 *
 * Copyright (C) 2004-2005 Stelian Pop <stelian@popies.net>
 * Copyright (C) 2007-2009 Mattia Dongili <malattia@linux.it>
 *
 * Parts of this driver inspired from asus_acpi.c and ibm_acpi.c
 * which are copyrighted by their respective authors.
 *
 * The SNY6001 driver part is based on the sonypi driver which includes
 * material from:
 *
 * Copyright (C) 2001-2005 Stelian Pop <stelian@popies.net>
 *
 * Copyright (C) 2005 Narayanan R S <nars@kadamba.org>
 *
 * Copyright (C) 2001-2002 Alcôve <www.alcove.com>
 *
 * Copyright (C) 2001 Michael Ashley <m.ashley@unsw.edu.au>
 *
 * Copyright (C) 2001 Junichi Morita <jun1m@mars.dti.ne.jp>
 *
 * Copyright (C) 2000 Takaya Kinjo <t-kinjo@tc4.so-net.ne.jp>
 *
 * Copyright (C) 2000 Andrew Tridgell <tridge@valinux.com>
 *
 * Earlier work by Werner Almesberger, Paul `Rusty' Russell and Paul Mackerras.
 */

#include <linux/acpi.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/dmi.h>
#include <linux/input.h>

#include "sony-pic.h"

/***********************************************************
*                                                          *
*   This module based on sony-laptop from kernel sources   *
*       Sony Programmable IO Control - SPIC (SNY6001)      *
*                                                          *
***********************************************************/

int  sonypi_compat_init( void );
void sonypi_compat_exit(void);
void sonypi_compat_report_event( u8 event );

int compat;// = 0
module_param(compat, int, 0444);
MODULE_PARM_DESC( compat, "set this if you want to enable backward compatibility mode" );

static int camera;		/* = 0 */
module_param(camera, int, 0444);
MODULE_PARM_DESC(camera,
		 "set this to 1 to enable Motion Eye camera controls "
		 "(only use it if you have a C1VE or C1VN model)");

/********************
*    INPUT DEVICE   *
********************/

static void vgnux_input_sendkey( int key ){
	if( key ){
		input_report_key( vgnux_input_device, key, 1 );
		input_sync( vgnux_input_device );

		input_report_key( vgnux_input_device, key, 0 );
		input_sync( vgnux_input_device );
	}
}

static int vgnux_register_input( void ){

	int err = 0;
	int i;

	vgnux_input_device = input_allocate_device();
	if( !vgnux_input_device )return -ENOMEM;

	vgnux_input_device->name       = KBUILD_MODNAME;
	vgnux_input_device->id.bustype = BUS_ISA;
	vgnux_input_device->id.vendor  = PCI_VENDOR_ID_SONY;

	vgnux_input_device->keycodesize = sizeof( vgnux_input_keycode_map[0] );
	vgnux_input_device->keycodemax = ARRAY_SIZE( vgnux_input_keycode_map );
	vgnux_input_device->keycode = &vgnux_input_keycode_map;

	for( i = 0; vgnux_input_keycode_map[i] != KEY_RESERVED; i++ ){
		input_set_capability( vgnux_input_device, EV_KEY, vgnux_input_keycode_map[i] );
	}

	err = input_register_device( vgnux_input_device );
	if( err ) input_free_device( vgnux_input_device );

	return err;
}

static void vgnux_unregister_input( void ){
	input_unregister_device( vgnux_input_device );
}

/************************
*    Platform Device    *
************************/

static int sony_pf_add( void ){
	int ret = 0;

	ret = platform_driver_register( &sony_pf_driver );
	if (ret) goto out;

	sony_pf_device = platform_device_alloc( KBUILD_MODNAME, -1 );
	if (!sony_pf_device) {
		ret = -ENOMEM;
		goto out_platform_registered;
	}

	ret = platform_device_add(sony_pf_device);
	if (ret) goto out_platform_alloced;

	return 0;

out_platform_alloced:
	platform_device_put(sony_pf_device);
	sony_pf_device = NULL;
out_platform_registered:
	platform_driver_unregister(&sony_pf_driver);
out:
	return ret;
}

static void sony_pf_remove(void){
	platform_device_unregister(sony_pf_device);
	platform_driver_unregister(&sony_pf_driver);
}

/*****************************
*    low level spic calls    *
******************************/

#define ITERATIONS_LONG		10000
#define ITERATIONS_SHORT	10
#define wait_on_command(command, iterations) { \
	unsigned int n = iterations;               \
	while( --n && (command) )udelay(1);        \
	if (!n) printk( KERN_WARNING "[%s] command failed at %s : %s (line %d)\n", \
				KBUILD_MODNAME, __FILE__, __func__, __LINE__);                 \
}

u8 sony_pic_call1(u8 dev){
	u8 v1, v2;
	wait_on_command( inb_p( spic_dev.cur_ioport->io1.minimum + 4 ) & 2, ITERATIONS_LONG );
	outb( dev, spic_dev.cur_ioport->io1.minimum + 4 );
	v1 = inb_p( spic_dev.cur_ioport->io1.minimum + 4 );
	v2 = inb_p( spic_dev.cur_ioport->io1.minimum );
	//printk( KERN_NOTICE "[%s] %s(0x%.2x): 0x%.4x\n", KBUILD_MODNAME, __FUNCTION__, dev, (v2 << 8) | v1 );
	return v2;
}

u8 sony_pic_call2(u8 dev, u8 fn){
	u8 v1;
	wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG );
	outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
	wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG );
	outb(fn, spic_dev.cur_ioport->io1.minimum);
	v1 = inb_p(spic_dev.cur_ioport->io1.minimum);
	//printk( KERN_NOTICE "[%s] %s(0x%.2x - 0x%.2x): 0x%.4x\n", KBUILD_MODNAME, __FUNCTION__, dev, fn, v1 );
	return v1;
}

static u8 sony_pic_call3(u8 dev, u8 fn, u8 v){
	u8 v1;
	wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
	outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
	wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
	outb(fn, spic_dev.cur_ioport->io1.minimum);
	wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG);
	outb(v, spic_dev.cur_ioport->io1.minimum);
	v1 = inb_p(spic_dev.cur_ioport->io1.minimum);
	//printk( KERN_NOTICE "[%s] %s(0x%.2x - 0x%.2x - 0x%.2x): 0x%.4x\n", KBUILD_MODNAME, __FUNCTION__, dev, fn, v, v1 );
	return v1;
}

/*******************
*      CAMERA      *
*******************/
//only for export
static int __sony_pic_camera_ready(void){
	u8 v;
	v = sony_pic_call2(0x8f, SONYPI_CAMERA_STATUS);
	return (v != 0xff && (v & SONYPI_CAMERA_STATUS_READY));
}

static int __sony_pic_camera_off(void){
	if (!camera) {
		pr_warn("camera control not enabled\n");
		return -ENODEV;
	}

	wait_on_command(sony_pic_call3(0x90, SONYPI_CAMERA_PICTURE,
				SONYPI_CAMERA_MUTE_MASK),
			ITERATIONS_SHORT);

	if (spic_dev.camera_power) {
		sony_pic_call2(0x91, 0);
		spic_dev.camera_power = 0;
	}
	return 0;
}

static int __sony_pic_camera_on(void){
	int i, j, x;

	if (!camera) {
		pr_warn("camera control not enabled\n");
		return -ENODEV;
	}

	if (spic_dev.camera_power)return 0;

	for (j = 5; j > 0; j--) {

		for (x = 0; x < 100 && sony_pic_call2(0x91, 0x1); x++)
			msleep(10);
		sony_pic_call1(0x93);

		for (i = 400; i > 0; i--) {
			if( __sony_pic_camera_ready() ) break;
			msleep(10);
		}
		if( i ) break;
	}

	if (j == 0) {
		pr_warn("failed to power on camera\n");
		return -ENODEV;
	}

	wait_on_command( sony_pic_call3(0x90, SONYPI_CAMERA_CONTROL, 0x5a), ITERATIONS_SHORT );

	spic_dev.camera_power = 1;
	return 0;
}

/* External camera command (exported to the motion eye v4l driver) */
int sony_pic_camera_command(int command, u8 value){
	if (!camera) return -EIO;

	mutex_lock(&spic_dev.lock);

	switch (command) {
		case SONY_PIC_COMMAND_SETCAMERA:
			if( value ) __sony_pic_camera_on();
			else __sony_pic_camera_off();
			break;
		case SONY_PIC_COMMAND_SETCAMERABRIGHTNESS:
			wait_on_command( sony_pic_call3( 0x90, SONYPI_CAMERA_BRIGHTNESS, value ), ITERATIONS_SHORT );
			break;
		case SONY_PIC_COMMAND_SETCAMERACONTRAST:
			wait_on_command( sony_pic_call3( 0x90, SONYPI_CAMERA_CONTRAST, value ),   ITERATIONS_SHORT );
			break;
		case SONY_PIC_COMMAND_SETCAMERAHUE:
			wait_on_command( sony_pic_call3( 0x90, SONYPI_CAMERA_HUE, value ),        ITERATIONS_SHORT );
			break;
		case SONY_PIC_COMMAND_SETCAMERACOLOR:
			wait_on_command( sony_pic_call3( 0x90, SONYPI_CAMERA_COLOR, value ),      ITERATIONS_SHORT );
			break;
		case SONY_PIC_COMMAND_SETCAMERASHARPNESS:
			wait_on_command( sony_pic_call3( 0x90, SONYPI_CAMERA_SHARPNESS, value ),  ITERATIONS_SHORT );
			break;
		case SONY_PIC_COMMAND_SETCAMERAPICTURE:
			wait_on_command( sony_pic_call3( 0x90, SONYPI_CAMERA_PICTURE, value ),    ITERATIONS_SHORT );
			break;
		case SONY_PIC_COMMAND_SETCAMERAAGC:
			wait_on_command( sony_pic_call3( 0x90, SONYPI_CAMERA_AGC, value ),        ITERATIONS_SHORT );
			break;
		default:
			pr_err("sony_pic_camera_command invalid: %d\n", command);
			break;
	}
	mutex_unlock(&spic_dev.lock);
	return 0;
}
EXPORT_SYMBOL(sony_pic_camera_command);

/***************************************************************
*  gprs/edge modem (SZ460N and SZ210P), thanks to Joshua Wise  *
***************************************************************/
static void __sony_pic_set_wwanpower( u8 state ){
	state = !!state;
	if ( spic_dev.wwan_power == state ) return;
	sony_pic_call2( 0xB0, state );
	sony_pic_call1( 0x82 );
	spic_dev.wwan_power = state;
}

static ssize_t sony_pic_wwanpower_store( struct device *dev, struct device_attribute *attr, const char *buffer, size_t count ){
	unsigned long value;
	if (count > 31) return -EINVAL;
	if (kstrtoul(buffer, 10, &value)) return -EINVAL;

	mutex_lock(&spic_dev.lock);
	__sony_pic_set_wwanpower(value);
	mutex_unlock(&spic_dev.lock);

	return count;
}

static ssize_t sony_pic_wwanpower_show(struct device *dev, struct device_attribute *attr, char *buffer){
	ssize_t count;
	mutex_lock(&spic_dev.lock);
	count = sysfs_emit( buffer, "%d\n", spic_dev.wwan_power );
	mutex_unlock(&spic_dev.lock);
	return count;
}

/************************************
*  bluetooth subsystem power state  *
************************************/
static void __sony_pic_set_bluetoothpower(u8 state){
	state = !!state;
	if (spic_dev.bluetooth_power == state) return;
	sony_pic_call2(0x96, state);
	sony_pic_call1(0x82);
	spic_dev.bluetooth_power = state;
}

static ssize_t sony_pic_bluetoothpower_store( struct device *dev, struct device_attribute *attr, const char *buffer, size_t count ){
	unsigned long value;
	if (count > 31) return -EINVAL;
	if (kstrtoul(buffer, 10, &value)) return -EINVAL;
	mutex_lock(&spic_dev.lock);
	__sony_pic_set_bluetoothpower(value);
	mutex_unlock(&spic_dev.lock);
	return count;
}

static ssize_t sony_pic_bluetoothpower_show(struct device *dev, struct device_attribute *attr, char *buffer){
	ssize_t count = 0;
	mutex_lock(&spic_dev.lock);
	count = sysfs_emit( buffer, "%d\n", spic_dev.bluetooth_power );
	mutex_unlock(&spic_dev.lock);
	return count;
}

/***********************************************************
*  FAN0 information (reverse engineered from ACPI tables)  *
***********************************************************/
#define SONY_PIC_FAN0_STATUS	0x93
static int sony_pic_set_fanspeed(unsigned long value){
	return ec_write(SONY_PIC_FAN0_STATUS, value);
}

static int sony_pic_get_fanspeed(u8 *value){
	return ec_read(SONY_PIC_FAN0_STATUS, value);
}

static ssize_t sony_pic_fanspeed_store( struct device *dev, struct device_attribute *attr, const char *buffer, size_t count ){
	unsigned long value;
	if (count > 31)return -EINVAL;
	if (kstrtoul(buffer, 10, &value))return -EINVAL;
	if (sony_pic_set_fanspeed(value))return -EIO;
	return count;
}

static ssize_t sony_pic_fanspeed_show( struct device *dev, struct device_attribute *attr, char *buffer ){
	u8 value = 0;
	if (sony_pic_get_fanspeed(&value)) return -EIO;
	return sysfs_emit( buffer, "%d\n", value );
}

/************
*   ATTRS   *
************/

#define SPIC_ATTR(_name, _mode)					\
struct device_attribute spic_attr_##_name = __ATTR(_name,	\
		_mode, sony_pic_## _name ##_show,		\
		sony_pic_## _name ##_store)

static SPIC_ATTR(bluetoothpower, 0644);
static SPIC_ATTR(wwanpower, 0644);
static SPIC_ATTR(fanspeed, 0644);

static struct attribute *spic_attributes[] = {
	&spic_attr_bluetoothpower.attr,
	&spic_attr_wwanpower.attr,
	&spic_attr_fanspeed.attr,
	NULL
};

static const struct attribute_group spic_attribute_group = {
	.attrs = spic_attributes
};

/***********************************
*   ISR: some event is available   *
***********************************/

irqreturn_t sony_pic_irq_handler( int irq, void *dev_id ){
	int i, j;
	u8 ev = 0;
	u8 data_mask = 0;

	struct sony_pic_dev *dev = (struct sony_pic_dev *) dev_id;

	ev = inb_p( dev->cur_ioport->io1.minimum );
	if( dev->cur_ioport->io2.minimum ) data_mask = inb_p( dev->cur_ioport->io2.minimum );
	else data_mask = inb_p( dev->cur_ioport->io1.minimum + dev->evport_offset );

	/*
	printk( KERN_NOTICE "[%s] event [%.2x] mask [%.2x] port 0x%.4x(+0x%.2x)\n",
		KBUILD_MODNAME,
		ev,
		data_mask,
		dev->cur_ioport->io1.minimum,
		dev->evport_offset
	);
	*/

	if (ev == 0x00 || ev == 0xff) return IRQ_HANDLED;

	for (i = 0; dev->event_types[i].data; i++) {
		if( data_mask != dev->event_types[i].data ) continue;
		for( j = 0; dev->event_types[i].events[j].data; j++ ) {
			if( ev == dev->event_types[i].events[j].data ) {
				vgnux_input_sendkey( dev->event_types[i].events[j].key );

				//events were thrown out as unnecessary
				//sonypi_compat_report_event( dev->event_types[i].events[j].event );

				return IRQ_HANDLED;
			}
		}
	}

	//Still not able to decode the event try to pass it over to the minidriver
	if( dev->handle_irq && dev->handle_irq(data_mask, ev) == 0 ) return IRQ_HANDLED;

	printk( KERN_WARNING "[%s] unknown event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n",
		KBUILD_MODNAME,
		ev,
		data_mask,
		dev->cur_ioport->io1.minimum,
		dev->evport_offset
	);
	return IRQ_HANDLED;
}

static int type3_handle_irq( const u8 data_mask, const u8 ev ){
	/*
	 * 0x31 could mean we have to take some extra action and wait for
	 * the next irq for some Type3 models, it will generate a new
	 * irq and we can read new data from the device:
	 *  - 0x5c and 0x5f requires 0xA0
	 *  - 0x61 requires 0xB3
	 */
	if( data_mask == 0x31 ){
		if ( ev == 0x5c || ev == 0x5f ) sony_pic_call1( 0xA0 );
		else if( ev == 0x61 ) sony_pic_call1( 0xB3 );
		return 0;
	}
	return 1;
}

/***********************
*    ACPI RESOURCES    *
***********************/
static acpi_status sony_pic_read_possible_resource( struct acpi_resource *resource, void *context ){
	u32 i;
	struct sony_pic_dev *dev = (struct sony_pic_dev *)context;

	switch (resource->type) {
	case ACPI_RESOURCE_TYPE_START_DEPENDENT:
		{
			/* start IO enumeration */
			struct sony_pic_ioport *ioport = kzalloc(sizeof(*ioport), GFP_KERNEL);
			if (!ioport)
				return AE_ERROR;

			list_add(&ioport->list, &dev->ioports);
			return AE_OK;
		}

	case ACPI_RESOURCE_TYPE_END_DEPENDENT:
		/* end IO enumeration */
		return AE_OK;

	case ACPI_RESOURCE_TYPE_IRQ:
		{
			struct acpi_resource_irq *p = &resource->data.irq;
			struct sony_pic_irq *interrupt = NULL;
			if (!p || !p->interrupt_count) {
				/*
				 * IRQ descriptors may have no IRQ# bits set,
				 * particularly those those w/ _STA disabled
				 */
				printk( KERN_NOTICE "[%s] Blank IRQ resource\n", KBUILD_MODNAME );
				return AE_OK;
			}
			for (i = 0; i < p->interrupt_count; i++) {
				if (!p->interrupts[i]) {
					pr_warn( "Invalid IRQ %d\n", p->interrupts[i] );
					continue;
				}
				interrupt = kzalloc(sizeof(*interrupt), GFP_KERNEL );
				if( !interrupt ) return AE_ERROR;

				list_add(&interrupt->list, &dev->interrupts);
				interrupt->irq.triggering = p->triggering;
				interrupt->irq.polarity = p->polarity;
				interrupt->irq.shareable = p->shareable;
				interrupt->irq.interrupt_count = 1;
				interrupt->irq.interrupts[0] = p->interrupts[i];
			}
			return AE_OK;
		}
	case ACPI_RESOURCE_TYPE_IO:
		{
			struct acpi_resource_io *io = &resource->data.io;
			struct sony_pic_ioport *ioport =
				list_first_entry(&dev->ioports, struct sony_pic_ioport, list);
			if (!io) {
				printk( KERN_NOTICE "[%s] Blank IO resource\n", KBUILD_MODNAME );
				return AE_OK;
			}

			if (!ioport->io1.minimum) {
				memcpy(&ioport->io1, io, sizeof(*io));
				printk( KERN_NOTICE "[%s] IO1 at 0x%.4x (0x%.2x)\n", KBUILD_MODNAME, ioport->io1.minimum, ioport->io1.address_length );
			}
			else if (!ioport->io2.minimum) {
				memcpy(&ioport->io2, io, sizeof(*io));
				printk( KERN_NOTICE "[%s] IO2 at 0x%.4x (0x%.2x)\n", KBUILD_MODNAME, ioport->io2.minimum, ioport->io2.address_length );
			}
			else {
				pr_err( "Unknown SPIC Type, more than 2 IO Ports\n" );
				return AE_ERROR;
			}
			return AE_OK;
		}

	case ACPI_RESOURCE_TYPE_END_TAG:
		return AE_OK;

	default:
		printk( KERN_NOTICE "[%s] Resource %d isn't an IRQ nor an IO port\n", KBUILD_MODNAME, resource->type );
		return AE_CTRL_TERMINATE;

	}
}

static int sony_pic_possible_resources( struct acpi_device *device ){
	int result = 0;
	acpi_status status = AE_OK;

	if (!device) return -EINVAL;

	/* get device status */
	/* see acpi_pci_link_get_current acpi_pci_link_get_possible */
	printk( KERN_NOTICE "[%s] Evaluating _STA\n", KBUILD_MODNAME );
	result = acpi_bus_get_status(device);
	if( result ){
		pr_warn("Unable to read status\n");
		goto end;
	}

	if( !device->status.enabled ) printk( KERN_NOTICE "[%s] Device disabled\n", KBUILD_MODNAME );
	else printk( KERN_NOTICE "[%s] Device enabled\n", KBUILD_MODNAME );

	//Query and parse 'method'
	printk( KERN_NOTICE "[%s] Evaluating %s\n", KBUILD_MODNAME, METHOD_NAME__PRS );
	status = acpi_walk_resources( device->handle, METHOD_NAME__PRS, sony_pic_read_possible_resource, &spic_dev );
	if( ACPI_FAILURE(status) ){
		pr_warn( "Failure evaluating %s\n", METHOD_NAME__PRS );
		result = -ENODEV;
	}
end:
	return result;
}

/***************************
*    DETECT DEVICE TYPE    *
***************************/

static void sony_pic_detect_device_type( struct sony_pic_dev *dev ){

	struct pci_dev *pcidev;

	pcidev = pci_get_device( PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, NULL );
	if( pcidev ){
		dev->model = SONYPI_DEVICE_TYPE1;
		dev->evport_offset = SONYPI_TYPE1_OFFSET;
		dev->event_types = dummy_events;
		goto out;
	}

	pcidev = pci_get_device( PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, NULL );
	if( pcidev ){
		dev->model = SONYPI_DEVICE_TYPE2;
		dev->evport_offset = SONYPI_TYPE2_OFFSET;
		dev->event_types = dummy_events;
		goto out;
	}

	pcidev = pci_get_device( PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, NULL );//VGN-UX
	if( pcidev ){
		dev->model = SONYPI_DEVICE_TYPE3;
		dev->handle_irq = type3_handle_irq;
		dev->evport_offset = SONYPI_TYPE3_OFFSET;
		//dev->event_types = type3_events;
		dev->event_types = vgnux_events;
		goto out;
	}

	pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_4, NULL );
	if( pcidev ){
		dev->model = SONYPI_DEVICE_TYPE3;
		dev->handle_irq = type3_handle_irq;
		dev->evport_offset = SONYPI_TYPE3_OFFSET;
		dev->event_types = dummy_events;
		goto out;
	}

	pcidev = pci_get_device( PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_1, NULL );
	if( pcidev ){
		dev->model = SONYPI_DEVICE_TYPE3;
		dev->handle_irq = type3_handle_irq;
		dev->evport_offset = SONYPI_TYPE3_OFFSET;
		dev->event_types = dummy_events;
		goto out;
	}

	/* default */
	dev->model = SONYPI_DEVICE_TYPE2;
	dev->evport_offset = SONYPI_TYPE2_OFFSET;
	dev->event_types = dummy_events;

out:
	pci_dev_put(pcidev);

	pr_info("[%s]detected Type%d model\n",
		KBUILD_MODNAME,
		dev->model == SONYPI_DEVICE_TYPE1 ? 1 :
		dev->model == SONYPI_DEVICE_TYPE2 ? 2 : 3 );
}

/*************************
*    SPIC DEVICE INIT    *
*************************/
//Based on drivers/acpi/pci_link.c:acpi_pci_link_set
//Call _SRS to set current resources

static int sony_pic_enable( struct acpi_device *device, struct sony_pic_ioport *ioport, struct sony_pic_irq *irq ){
	acpi_status status;
	int result = 0;
	/* Type 1 resource layout is:
	 *    IO
	 *    IO
	 *    IRQNoFlags
	 *    End
	 *
	 * Type 2 and 3 resource layout is:
	 *    IO
	 *    IRQNoFlags
	 *    End
	 */
	struct {
		struct acpi_resource res1;
		struct acpi_resource res2;
		struct acpi_resource res3;
		struct acpi_resource res4;
	} *resource;
	struct acpi_buffer buffer = { 0, NULL };

	if (!ioport || !irq) return -EINVAL;

	/* init acpi_buffer */
	resource = kzalloc(sizeof(*resource) + 1, GFP_KERNEL);
	if (!resource) return -ENOMEM;

	buffer.length = sizeof(*resource) + 1;
	buffer.pointer = resource;

	/* setup Type 1 resources */
	if (spic_dev.model == SONYPI_DEVICE_TYPE1) {

		/* setup io resources */
		resource->res1.type = ACPI_RESOURCE_TYPE_IO;
		resource->res1.length = sizeof(struct acpi_resource);
		memcpy(&resource->res1.data.io, &ioport->io1, sizeof(struct acpi_resource_io));

		resource->res2.type = ACPI_RESOURCE_TYPE_IO;
		resource->res2.length = sizeof(struct acpi_resource);
		memcpy(&resource->res2.data.io, &ioport->io2, sizeof(struct acpi_resource_io));

		/* setup irq resource */
		resource->res3.type = ACPI_RESOURCE_TYPE_IRQ;
		resource->res3.length = sizeof(struct acpi_resource);
		memcpy(&resource->res3.data.irq, &irq->irq, sizeof(struct acpi_resource_irq));
		/* we requested a shared irq */
		resource->res3.data.irq.shareable = ACPI_SHARED;

		resource->res4.type = ACPI_RESOURCE_TYPE_END_TAG;
		resource->res4.length = sizeof(struct acpi_resource);
	}
	/* setup Type 2/3 resources */
	else {
		/* setup io resource */
		resource->res1.type = ACPI_RESOURCE_TYPE_IO;
		resource->res1.length = sizeof(struct acpi_resource);
		memcpy(&resource->res1.data.io, &ioport->io1,
				sizeof(struct acpi_resource_io));

		/* setup irq resource */
		resource->res2.type = ACPI_RESOURCE_TYPE_IRQ;
		resource->res2.length = sizeof(struct acpi_resource);
		memcpy(&resource->res2.data.irq, &irq->irq,	sizeof(struct acpi_resource_irq));
		/* we requested a shared irq */
		resource->res2.data.irq.shareable = ACPI_SHARED;

		resource->res3.type = ACPI_RESOURCE_TYPE_END_TAG;
		resource->res3.length = sizeof(struct acpi_resource);
	}

	/* Attempt to set the resource */
	printk( KERN_NOTICE "[%s] Evaluating _SRS\n", KBUILD_MODNAME );
	status = acpi_set_current_resources(device->handle, &buffer);

	/* check for total failure */
	if (ACPI_FAILURE(status)) {
		pr_err("Error evaluating _SRS\n");
		result = -ENODEV;
		goto end;
	}

	/* Necessary device initializations calls (from sonypi) */
	sony_pic_call1(0x82);
	sony_pic_call2(0x81, 0xff);
	sony_pic_call1(compat ? 0x92 : 0x82);

end:
	kfree(resource);
	return result;
}

//Disable the spic device by calling its _DIS method
static int sony_pic_disable( struct acpi_device *device ){
	acpi_status ret = acpi_evaluate_object( device->handle, "_DIS", NULL, NULL );
	if( ACPI_FAILURE(ret) && ret != AE_NOT_FOUND ) return -ENXIO;
	printk( KERN_NOTICE "[%s] Device disabled\n", KBUILD_MODNAME );
	return 0;
}

static int sony_pic_add( struct acpi_device* device ) {
	int result;
	struct sony_pic_ioport *io, *tmp_io;
	struct sony_pic_irq *irq, *tmp_irq;

	printk( KERN_NOTICE "[%s] SPIC setup...\n", KBUILD_MODNAME );

	spic_dev.acpi_dev = device;
	strcpy(acpi_device_class(device), "sony/hotkey");
	sony_pic_detect_device_type(&spic_dev);
	mutex_init(&spic_dev.lock);

	/* read _PRS resources */
	result = sony_pic_possible_resources( device );
	if( result ){
		pr_err( "[%s]Unable to read possible resources\n", KBUILD_MODNAME );
		goto err_free_resources;
	}

	//setup input device
	result = vgnux_register_input();
	if( result ){
		pr_err("[%s]Unable to create input device\n", KBUILD_MODNAME );
		goto err_free_resources;
	}

	result = sonypi_compat_init();
	if( result ) goto err_remove_input;

	/* request io port */
	list_for_each_entry_reverse(io, &spic_dev.ioports, list) {
		if (request_region(io->io1.minimum, io->io1.address_length,
					"Sony Programmable I/O Device")) {
			printk( KERN_NOTICE "[%s] I/O port1: 0x%.4x (0x%.4x) + 0x%.2x\n",
				KBUILD_MODNAME,
				io->io1.minimum,
				io->io1.maximum,
				io->io1.address_length
			);
			/* Type 1 have 2 ioports */
			if (io->io2.minimum) {
				if (request_region(io->io2.minimum,
						io->io2.address_length,
						"Sony Programmable I/O Device")) {
					printk( KERN_NOTICE "[%s] I/O port2: 0x%.4x (0x%.4x) + 0x%.2x\n",
						KBUILD_MODNAME,
						io->io2.minimum,
						io->io2.maximum,
						io->io2.address_length
					);
					spic_dev.cur_ioport = io;
					break;
				}
				else {
					printk( KERN_ERR "[%s] Unable to get I/O port2: 0x%.4x (0x%.4x) + 0x%.2x\n",
						KBUILD_MODNAME,
						io->io2.minimum,
						io->io2.maximum,
						io->io2.address_length
					);
					release_region( io->io1.minimum, io->io1.address_length );
				}
			}
			else {
				spic_dev.cur_ioport = io;
				break;
			}
		}
	}
	if (!spic_dev.cur_ioport) {
		pr_err( "[%s]Failed to request_region\n", KBUILD_MODNAME );
		result = -ENODEV;
		goto err_remove_compat;
	}

	/* request IRQ */
	list_for_each_entry_reverse(irq, &spic_dev.interrupts, list) {
		if( !request_irq(irq->irq.interrupts[0], sony_pic_irq_handler, 0, KBUILD_MODNAME, &spic_dev) ){
			printk( KERN_NOTICE "[%s] IRQ: %d - triggering: %d - polarity: %d - shr: %d\n",
				KBUILD_MODNAME,
				irq->irq.interrupts[0],
				irq->irq.triggering,
				irq->irq.polarity,
				irq->irq.shareable
			);
			spic_dev.cur_irq = irq;
			break;
		}
	}
	if (!spic_dev.cur_irq) {
		pr_err( "[%s]Failed to request_irq\n", KBUILD_MODNAME );
		result = -ENODEV;
		goto err_release_region;
	}

	/* set resource status _SRS */
	result = sony_pic_enable(device, spic_dev.cur_ioport, spic_dev.cur_irq);
	if ( result ) {
		printk( KERN_ERR "[%s] Couldn't enable device\n", KBUILD_MODNAME );
		goto err_free_irq;
	}

	spic_dev.bluetooth_power = -1;
	/* create device attributes */
	result = sony_pf_add();
	if (result) goto err_disable_device;

	result = sysfs_create_group(&sony_pf_device->dev.kobj, &spic_attribute_group);
	if (result) goto err_remove_pf;

	pr_info( "[%s] SPIC setup done.\n", KBUILD_MODNAME );
	return 0;

err_remove_pf:
	sony_pf_remove();

err_disable_device:
	sony_pic_disable(device);

err_free_irq:
	free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev);

err_release_region:
	release_region(spic_dev.cur_ioport->io1.minimum, spic_dev.cur_ioport->io1.address_length);
	if (spic_dev.cur_ioport->io2.minimum)
		release_region(spic_dev.cur_ioport->io2.minimum, spic_dev.cur_ioport->io2.address_length);

err_remove_compat:
	sonypi_compat_exit();

err_remove_input:
	vgnux_unregister_input();

err_free_resources:
	list_for_each_entry_safe(io, tmp_io, &spic_dev.ioports, list) {
		list_del(&io->list);
		kfree(io);
	}
	list_for_each_entry_safe(irq, tmp_irq, &spic_dev.interrupts, list) {
		list_del(&irq->list);
		kfree(irq);
	}
	spic_dev.cur_ioport = NULL;
	spic_dev.cur_irq = NULL;

	return result;
}

static int sony_pic_remove( struct acpi_device* device ){
	struct sony_pic_ioport *io, *tmp_io;
	struct sony_pic_irq *irq, *tmp_irq;

	if( sony_pic_disable(device) ) {
		pr_err("Couldn't disable device\n");
		return -ENXIO;
	}

	free_irq(spic_dev.cur_irq->irq.interrupts[0], &spic_dev);
	release_region(spic_dev.cur_ioport->io1.minimum, spic_dev.cur_ioport->io1.address_length);
	if (spic_dev.cur_ioport->io2.minimum)
		release_region(spic_dev.cur_ioport->io2.minimum, spic_dev.cur_ioport->io2.address_length);

	sonypi_compat_exit();
	vgnux_unregister_input();

	/* pf attrs */
	sysfs_remove_group(&sony_pf_device->dev.kobj, &spic_attribute_group);
	sony_pf_remove();

	list_for_each_entry_safe(io, tmp_io, &spic_dev.ioports, list) {
		list_del(&io->list);
		kfree(io);
	}
	list_for_each_entry_safe(irq, tmp_irq, &spic_dev.interrupts, list) {
		list_del(&irq->list);
		kfree(irq);
	}
	spic_dev.cur_ioport = NULL;
	spic_dev.cur_irq = NULL;

	printk( KERN_NOTICE "[%s] "SONY_PIC_DRIVER_NAME " removed.\n", KBUILD_MODNAME );
	return 0;
}

#ifdef CONFIG_PM_SLEEP
static int sony_pic_suspend( struct device* dev ){
	if( sony_pic_disable(to_acpi_device(dev)) ) return -ENXIO;
	return 0;
}

static int sony_pic_resume( struct device* dev ){
	sony_pic_enable( to_acpi_device(dev), spic_dev.cur_ioport, spic_dev.cur_irq );
	return 0;
}
#endif

/********************
*    MODULE INIT    *
********************/

static int __init onLoad( void ){

	int result = 0;

	printk( KERN_NOTICE "%s is here.\n", KBUILD_MODNAME );

	if( !dmi_check_system( sonypi_dmi_table ) ){
		printk( KERN_NOTICE "[%s] Compatable hardware not found.\n", KBUILD_MODNAME );
		return -ENODEV;
	}

	result = acpi_bus_register_driver( &sony_pic_driver );
	if( result ) printk( KERN_ERR "[%s] Unable to register SPIC driver\n", KBUILD_MODNAME );
	return result;
}

static void __exit onUnload( void ){
	acpi_bus_unregister_driver( &sony_pic_driver );
	printk( KERN_NOTICE "%s has been unloaded.\n", KBUILD_MODNAME );
}

module_init( onLoad );
module_exit( onUnload );
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE( acpi, sony_pic_device_ids );


code:
#pragma once

#include <uapi/linux/input-event-codes.h>

#define SONY_PIC_DRIVER_NAME "Sony Programmable IO Control Driver"

#define SONYPI_TYPE1_OFFSET 0x04
#define SONYPI_TYPE2_OFFSET 0x12
#define SONYPI_TYPE3_OFFSET 0x12

#define SONYPI_DEVICE_TYPE1 0x00000001
#define SONYPI_DEVICE_TYPE2 0x00000002
#define SONYPI_DEVICE_TYPE3 0x00000004

/***************
*     INPUT    *
***************/

struct input_dev* vgnux_input_device;

static int vgnux_input_keycode_map[] = {
	KEY_PROG1,
	KEY_PROG2,
	KEY_PROG3,
	KEY_CAMERA,
	KEY_WLAN,
	KEY_WWAN,
	KEY_DISPLAY_OFF,

	KEY_RESERVED//list terminator
};

/************************
*    Platform Device    *
************************/

static struct platform_driver sony_pf_driver = {
	.driver = {
		   .name = KBUILD_MODNAME,
		   }
};
static struct platform_device* sony_pf_device;

/***************
*    CAMERA    *
***************/
//camera tests and poweron/poweroff
#define SONYPI_CAMERA_PICTURE      5
#define SONYPI_CAMERA_CONTROL     0x10

#define SONYPI_CAMERA_BRIGHTNESS  0
#define SONYPI_CAMERA_CONTRAST    1
#define SONYPI_CAMERA_HUE         2
#define SONYPI_CAMERA_COLOR       3
#define SONYPI_CAMERA_SHARPNESS   4

#define SONYPI_CAMERA_EXPOSURE_MASK      0xC
#define SONYPI_CAMERA_WHITE_BALANCE_MASK 0x3
#define SONYPI_CAMERA_PICTURE_MODE_MASK  0x30
#define SONYPI_CAMERA_MUTE_MASK          0x40

//the rest don't need a loop until not 0xff
#define SONYPI_CAMERA_AGC          6
#define SONYPI_CAMERA_AGC_MASK     0x30
#define SONYPI_CAMERA_SHUTTER_MASK 0x7

#define SONYPI_CAMERA_SHUTDOWN_REQUEST 7
#define SONYPI_CAMERA_CONTROL          0x10

#define SONYPI_CAMERA_STATUS            7
#define SONYPI_CAMERA_STATUS_READY      0x2
#define SONYPI_CAMERA_STATUS_POSITION   0x4

#define SONYPI_DIRECTION_BACKWARDS 0x4

#define SONYPI_CAMERA_REVISION    8
#define SONYPI_CAMERA_ROMVERSION  9

//used only for communication between v4l and sony-laptop
#define SONY_PIC_COMMAND_GETCAMERA           1	/* obsolete */
#define SONY_PIC_COMMAND_SETCAMERA           2
#define SONY_PIC_COMMAND_GETCAMERABRIGHTNESS 3	/* obsolete */
#define SONY_PIC_COMMAND_SETCAMERABRIGHTNESS 4
#define SONY_PIC_COMMAND_GETCAMERACONTRAST   5	/* obsolete */
#define SONY_PIC_COMMAND_SETCAMERACONTRAST   6
#define SONY_PIC_COMMAND_GETCAMERAHUE        7	/* obsolete */
#define SONY_PIC_COMMAND_SETCAMERAHUE        8
#define SONY_PIC_COMMAND_GETCAMERACOLOR      9	/* obsolete */
#define SONY_PIC_COMMAND_SETCAMERACOLOR      10
#define SONY_PIC_COMMAND_GETCAMERASHARPNESS  11	/* obsolete */
#define SONY_PIC_COMMAND_SETCAMERASHARPNESS  12
#define SONY_PIC_COMMAND_GETCAMERAPICTURE    13	/* obsolete */
#define SONY_PIC_COMMAND_SETCAMERAPICTURE    14
#define SONY_PIC_COMMAND_GETCAMERAAGC        15	/* obsolete */
#define SONY_PIC_COMMAND_SETCAMERAAGC        16
#define SONY_PIC_COMMAND_GETCAMERADIRECTION  17	/* obsolete */
#define SONY_PIC_COMMAND_GETCAMERAROMVERSION 18	/* obsolete */
#define SONY_PIC_COMMAND_GETCAMERAREVISION   19	/* obsolete */

/****************/

struct sony_pic_irq {
	struct acpi_resource_irq irq;
	struct list_head         list;
};

struct sony_pic_ioport {
	struct acpi_resource_io io1;
	struct acpi_resource_io io2;
	struct list_head        list;
};

struct sony_pic_dev {
	struct acpi_device*             acpi_dev;
	struct sony_pic_irq*            cur_irq;
	struct sony_pic_ioport*         cur_ioport;
	struct list_head                interrupts;
	struct list_head                ioports;
	struct mutex                    lock;
	const struct sonypi_eventtypes* event_types;
	int                             (*handle_irq)(const u8, const u8);
	int                             model;
	u16                             evport_offset;
	u8                              camera_power;
	u8                              bluetooth_power;
	u8                              wwan_power;
};

static struct sony_pic_dev spic_dev = {
	.interrupts = LIST_HEAD_INIT(spic_dev.interrupts),
	.ioports    = LIST_HEAD_INIT(spic_dev.ioports),
};

/**************************
*         EVENTS          *
**************************/

struct sonypi_event {
	u8  data;
	int key;
};

struct sonypi_eventtypes {
	u8                         data;
	const struct sonypi_event* events;
};

/***VGN-UX DB***/

static const struct sonypi_event vgnux_buttons[] = {
	{ 0x01, KEY_PROG1  },//menu
	{ 0x10, KEY_PROG2  },//zoomin
	{ 0x20, KEY_PROG3  },//zoomout
	{ 0x40, KEY_CAMERA },//cam
	{ 0,    0          }
};

static const struct sonypi_event vgnux_fnkeys[] = {
	{ 0x11, KEY_WWAN },//fn+f
	{ 0x1f, 0        },//fn release
	{ 0x36, 0        },//fn only
	{ 0,    0        }
};

static const struct sonypi_event vgnux_power[] = {
	{ 0x56, 0               },//dock in
	{ 0x57, 0               },//dock out
	{ 0x59, KEY_WLAN        },//wlan on
	{ 0x5a, KEY_WLAN        },//wlan off
	{ 0xb9, KEY_DISPLAY_OFF },//hold
	{ 0,    0 }
};

static const struct sonypi_event vgnux_battery[] = {
	{ 0x20, 0 },//insert
	{ 0x30, 0 },//remove
	{ 0,    0 }
};

static const struct sonypi_eventtypes vgnux_events[] = {
	{ 0x05, vgnux_buttons },
	{ 0x21, vgnux_fnkeys  },
	{ 0x31, vgnux_power   },
	{ 0x41, vgnux_battery },
	{ 0,    0             }
};

static const struct sonypi_eventtypes dummy_events[] = {
	{ 0, 0 }
};

/***********************
*    DRIVER STRUCTS    *
***********************/
static int sony_pic_add( struct acpi_device* device );
static int sony_pic_remove( struct acpi_device* device );

#ifdef CONFIG_PM_SLEEP
static int sony_pic_suspend( struct device* dev );
static int sony_pic_resume( struct device* dev );
#endif

static SIMPLE_DEV_PM_OPS( sony_pic_pm, sony_pic_suspend, sony_pic_resume );

static const struct acpi_device_id sony_pic_device_ids[] = {
	{ "SNY6001", 0 },
	{ "",        0 },
};

static struct acpi_driver sony_pic_driver = {
	.name  = SONY_PIC_DRIVER_NAME,
	.class = "sony-pic",
	.ids   = sony_pic_device_ids,
	.owner = THIS_MODULE,
	.ops = {
		.add    = sony_pic_add,
		.remove = sony_pic_remove,
		},
	.drv.pm = &sony_pic_pm,
};

const struct dmi_system_id sonypi_dmi_table[] __initconst = {
	{
		.ident = "Sony Vaio",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
			DMI_MATCH(DMI_PRODUCT_NAME, "VGN-"),
		},
	},
	{ }
};


code:
share/man/man7/free-software.7 copied from /tmp/src_deblob//ADD_share^man^man7^free-software.7
share/man/man7/fsdg.7 copied from /tmp/src_deblob//ADD_share^man^man7^fsdg.7
/usr/src/distrib/amd64/ramdisk_cd/list.local patched from /tmp/src_deblob//distrib^amd64^ramdisk_cd^list.local.patch
/usr/src/distrib/i386/ramdisk_cd/list.local patched from /tmp/src_deblob//distrib^i386^ramdisk_cd^list.local.patch
/usr/src/distrib/sets/lists/base/md.amd64 patched from /tmp/src_deblob//distrib^sets^lists^base^md.amd64.patch
/usr/src/distrib/sets/lists/base/md.i386 patched from /tmp/src_deblob//distrib^sets^lists^base^md.i386.patch
/usr/src/distrib/sets/lists/base/mi patched from /tmp/src_deblob//distrib^sets^lists^base^mi.patch
/usr/src/distrib/sets/lists/man/mi patched from /tmp/src_deblob//distrib^sets^lists^man^mi.patch
/usr/src/share/man/man4/Makefile patched from /tmp/src_deblob//share^man^man4^Makefile.patch
/usr/src/share/man/man7/Makefile patched from /tmp/src_deblob//share^man^man7^Makefile.patch
/usr/src/usr.sbin/pkg_add/Makefile patched from /tmp/src_deblob//usr.sbin^pkg_add^Makefile.patch
distrib/miniroot/install.sub copied from /tmp/src_rebrand/ADD_distrib^miniroot^install.sub
etc/motd copied from /tmp/src_rebrand/ADD_etc^motd
etc/root/root.mail copied from /tmp/src_rebrand/ADD_etc^root^root.mail
/usr/src/distrib/amd64/cdfs/Makefile patched from /tmp/src_rebrand/distrib^amd64^cdfs^Makefile.patch
/usr/src/distrib/amd64/common/install.md patched from /tmp/src_rebrand/distrib^amd64^common^install.md.patch
/usr/src/distrib/amd64/iso/Makefile patched from /tmp/src_rebrand/distrib^amd64^iso^Makefile.patch
/usr/src/distrib/i386/cdfs/Makefile patched from /tmp/src_rebrand/distrib^i386^cdfs^Makefile.patch
/usr/src/distrib/i386/common/install.md patched from /tmp/src_rebrand/distrib^i386^common^install.md.patch
/usr/src/distrib/i386/iso/Makefile patched from /tmp/src_rebrand/distrib^i386^iso^Makefile.patch
/usr/src/distrib/miniroot/dot.profile patched from /tmp/src_rebrand/distrib^miniroot^dot.profile.patch
/usr/src/distrib/sets/lists/base/md.amd64 patched from /tmp/src_rebrand/distrib^sets^lists^base^md.amd64.patch
/usr/src/distrib/sets/lists/base/md.i386 patched from /tmp/src_rebrand/distrib^sets^lists^base^md.i386.patch
/usr/src/gnu/../usr.sbin/bind/config.guess patched from /tmp/src_rebrand/gnu^..^usr.sbin^bind^config.guess.patch
/usr/src/gnu/../usr.sbin/unbound/config.guess patched from /tmp/src_rebrand/gnu^..^usr.sbin^unbound^config.guess.patch
/usr/src/gnu/lib/libiberty/config.guess patched from /tmp/src_rebrand/gnu^lib^libiberty^config.guess.patch
/usr/src/gnu/lib/libobjc/config.guess patched from /tmp/src_rebrand/gnu^lib^libobjc^config.guess.patch
/usr/src/gnu/lib/libstdc++/config.guess patched from /tmp/src_rebrand/gnu^lib^libstdc++^config.guess.patch
/usr/src/gnu/share/config.guess patched from /tmp/src_rebrand/gnu^share^config.guess.patch
/usr/src/gnu/usr.bin/binutils-2.17/config.guess patched from /tmp/src_rebrand/gnu^usr.bin^binutils-2.17^config.guess.patch
/usr/src/gnu/usr.bin/binutils/config.guess patched from /tmp/src_rebrand/gnu^usr.bin^binutils^config.guess.patch
/usr/src/gnu/usr.bin/gcc/config.guess patched from /tmp/src_rebrand/gnu^usr.bin^gcc^config.guess.patch
/usr/src/gnu/usr.bin/perl/Configure patched from /tmp/src_rebrand/gnu^usr.bin^perl^Configure.patch
/usr/src/gnu/usr.bin/perl/Makefile.SH patched from /tmp/src_rebrand/gnu^usr.bin^perl^Makefile.SH.patch
!!! /usr/src/gnu/usr.bin/perl/Makefile.bsd-wrapper NOT patched from /tmp/src_rebrand/gnu^usr.bin^perl^Makefile.bsd-wrapper.patch
/usr/src/gnu/usr.bin/texinfo/config.guess patched from /tmp/src_rebrand/gnu^usr.bin^texinfo^config.guess.patch
/usr/src/usr.bin/sendbug/sendbug.c patched from /tmp/src_rebrand/usr.bin^sendbug^sendbug.c.patch
/usr/src/sys/arch/amd64/stand/libsa/biosdev.c patched from /tmp/sys_rebrand/arch^amd64^stand^libsa^biosdev.c.patch
/usr/src/sys/arch/i386/stand/libsa/biosdev.c patched from /tmp/sys_rebrand/arch^i386^stand^libsa^biosdev.c.patch
/usr/src/sys/conf/newvers.sh patched from /tmp/sys_rebrand/conf^newvers.sh.patch
/usr/src/sys/stand/boot/boot.c patched from /tmp/sys_rebrand/stand^boot^boot.c.patch
dev/microcode/adw deleted
dev/microcode/afb deleted
dev/microcode/atmel deleted
dev/microcode/bnx deleted
dev/microcode/bwi deleted
dev/microcode/cirruslogic deleted
dev/microcode/cyclades deleted
dev/microcode/esa deleted
dev/microcode/fxp deleted
dev/microcode/ises deleted
dev/microcode/kue deleted
dev/microcode/myx deleted
dev/microcode/neomagic deleted
dev/microcode/ral deleted
dev/microcode/rum deleted
dev/microcode/siop deleted
dev/microcode/symbol deleted
dev/microcode/tht deleted
dev/microcode/tigon deleted
dev/microcode/tusb3410 deleted
dev/microcode/typhoon deleted
dev/microcode/udl deleted
dev/microcode/yds deleted
dev/microcode/zydas deleted
dev/pci/adv_pci.c deleted
dev/pci/adw_pci.c deleted
dev/pci/esa.c deleted
dev/pci/esareg.h deleted
dev/pci/esavar.h deleted
/usr/src/sys/arch/amd64/conf/GENERIC patched from /tmp/sys_deblob/arch^amd64^conf^GENERIC.patch
/usr/src/sys/arch/amd64/conf/RAMDISK patched from /tmp/sys_deblob/arch^amd64^conf^RAMDISK.patch
/usr/src/sys/arch/amd64/conf/RAMDISK_CD patched from /tmp/sys_deblob/arch^amd64^conf^RAMDISK_CD.patch
/usr/src/sys/arch/i386/conf/GENERIC patched from /tmp/sys_deblob/arch^i386^conf^GENERIC.patch
/usr/src/sys/arch/i386/conf/RAMDISK patched from /tmp/sys_deblob/arch^i386^conf^RAMDISK.patch
/usr/src/sys/arch/i386/conf/RAMDISK_CD patched from /tmp/sys_deblob/arch^i386^conf^RAMDISK_CD.patch
/usr/src/sys/dev/microcode/Makefile patched from /tmp/sys_deblob/dev^microcode^Makefile.patch
/usr/src/sys/dev/pci/files.pci patched from /tmp/sys_deblob/dev^pci^files.pci.patch
app/xdm/config/LibertyBSD_15bpp.xpm copied from /ADD_app^xdm^config^LibertyBSD_15bpp.xpm
app/xdm/config/LibertyBSD_1bpp.xpm copied from /ADD_app^xdm^config^LibertyBSD_1bpp.xpm
app/xdm/config/LibertyBSD_4bpp.xpm copied from /ADD_app^xdm^config^LibertyBSD_4bpp.xpm
app/xdm/config/LibertyBSD_8bpp.xpm copied from /ADD_app^xdm^config^LibertyBSD_8bpp.xpm
/usr/xenocara//app/fvwm/sample.fvwmrc/system.fvwmrc patched from /app^fvwm^sample.fvwmrc^system.fvwmrc.patch
!!! /usr/xenocara//app/twm/config.guess NOT patched from /app^twm^config.guess.patch
/usr/xenocara//app/xdm/Makefile.bsd-wrapper patched from /app^xdm^Makefile.bsd-wrapper.patch
/usr/xenocara//app/xdm/config/Xresources.cpp patched from /app^xdm^config^Xresources.cpp.patch
/usr/xenocara//app/xlockmore/Makefile.bsd-wrapper patched from /app^xlockmore^Makefile.bsd-wrapper.patch
/usr/xenocara//distrib/sets/lists/xshare/mi patched from /distrib^sets^lists^xshare^mi.patch
/usr/xenocara//share/mk/bsd.xorg.mk patched from /share^mk^bsd.xorg.mk.patch
app/xdm/config/LibertyBSD_15bpp.xpm copied from /tmp/xenocara_rebrand/ADD_app^xdm^config^LibertyBSD_15bpp.xpm
app/xdm/config/LibertyBSD_1bpp.xpm copied from /tmp/xenocara_rebrand/ADD_app^xdm^config^LibertyBSD_1bpp.xpm
app/xdm/config/LibertyBSD_4bpp.xpm copied from /tmp/xenocara_rebrand/ADD_app^xdm^config^LibertyBSD_4bpp.xpm
app/xdm/config/LibertyBSD_8bpp.xpm copied from /tmp/xenocara_rebrand/ADD_app^xdm^config^LibertyBSD_8bpp.xpm
!!! /usr/xenocara//app/fvwm/sample.fvwmrc/system.fvwmrc NOT patched from /tmp/xenocara_rebrand/app^fvwm^sample.fvwmrc^system.fvwmrc.patch
!!! /usr/xenocara//app/twm/config.guess NOT patched from /tmp/xenocara_rebrand/app^twm^config.guess.patch
!!! /usr/xenocara//app/xdm/Makefile.bsd-wrapper NOT patched from /tmp/xenocara_rebrand/app^xdm^Makefile.bsd-wrapper.patch
!!! /usr/xenocara//app/xdm/config/Xresources.cpp NOT patched from /tmp/xenocara_rebrand/app^xdm^config^Xresources.cpp.patch
/usr/xenocara//app/xlockmore/Makefile.bsd-wrapper patched from /tmp/xenocara_rebrand/app^xlockmore^Makefile.bsd-wrapper.patch
!!! /usr/xenocara//distrib/sets/lists/xshare/mi NOT patched from /tmp/xenocara_rebrand/distrib^sets^lists^xshare^mi.patch
/usr/xenocara//share/mk/bsd.xorg.mk patched from /tmp/xenocara_rebrand/share^mk^bsd.xorg.mk.patch

repo_name: pecg/LibertyBSD


code:
.Dd $Mdocdate: April 16 2016 $
.Dt FREE-SOFTWARE 7
.Os
.Sh NAME
.Nm free-software
.Nd philosophy of software freedom
.Sh DEFINITION
"Free software" means software that respects users' freedom and community. Roughly, it
means that the users have the freedom to run, copy, distribute, study, change and improve
the software. Thus, "free software" is a matter of liberty, not price. To understand the
concept, you should think of "free" as in "free speech," not as in "free beer". We sometimes
call it "libre software" to show we do not mean it is gratis.
.Pp
We campaign for these freedoms because everyone deserves them. With these freedoms, the users
(both individually and collectively) control the program and what it does for them. When users
don't control the program, we call it a "nonfree" or "proprietary" program. The nonfree program
controls the users, and the developer controls the program; this makes the program an instrument
of unjust power.
.Pp
 A program is free software if the program's users have the four essential freedoms:

.Bl -bullet
.It
The freedom to run the program as you wish, for any purpose (freedom 0).
.It
The freedom to study how the program works, and change it so it does your computing as you wish (freedom 1). Access to the source code is a precondition for this.
.It
The freedom to redistribute copies so you can help your neighbor (freedom 2).
.It
The freedom to distribute copies of your modified versions to others (freedom 3). By doing this you can give the whole community a chance to benefit from your changes. Access to the source code is a precondition for this.
.El
.Pp
A program is free software if it gives users adequately all of these freedoms. Otherwise, it is nonfree. While we can distinguish various nonfree distribution schemes in terms of how far they fall short of being free, we consider them all equally unethical.

.Sh FREEDOMS CLARIFIED

In any given scenario, these freedoms must apply to whatever code we plan to make use of,
or lead others to make use of. For instance, consider a program A which automatically launches
a program B to handle some cases. If we plan to distribute A as it stands, that implies users
will need B, so we need to judge whether both A and B are free. However, if we plan to modify A
so that it doesn't use B, only A needs to be free; we can ignore B.
.Pp
The rest of this page clarifies certain points about what makes specific freedoms adequate or not.
.Pp
Freedom to distribute (freedoms 2 and 3) means you are free to redistribute copies, either with
or without modifications, either gratis or charging a fee for distribution, to anyone anywhere.
Being free to do these things means (among other things) that you do not have to ask or pay for
permission to do so.
.Pp
You should also have the freedom to make modifications and use them privately in your own work
or play, without even mentioning that they exist. If you do publish your changes, you should
not be required to notify anyone in particular, or in any particular way.
.Pp
The freedom to run the program means the freedom for any kind of person or organization to
use it on any kind of computer system, for any kind of overall job and purpose, without being
required to communicate about it with the developer or any other specific entity. In this
freedom, it is the user's purpose that matters, not the developer's purpose; you as a user
are free to run the program for your purposes, and if you distribute it to someone else, she
is then free to run it for her purposes, but you are not entitled to impose your purposes on her.
.Pp
The freedom to run the program as you wish means that you are not forbidden or stopped from doing
so. It has nothing to do with what functionality the program has, or whether it is useful for what
you want to do.
.Pp
The freedom to redistribute copies must include binary or executable forms of the program, as well
as source code, for both modified and unmodified versions. (Distributing programs in runnable form
is necessary for conveniently installable free operating systems.) It is OK if there is no way to
produce a binary or executable form for a certain program (since some languages don't support that
feature), but you must have the freedom to redistribute such forms should you find or develop a
way to make them.
.Pp
In order for freedoms 1 and 3 (the freedom to make changes and the freedom to publish the changed
versions) to be meaningful, you must have access to the source code of the program. Therefore,
accessibility of source code is a necessary condition for free software. Obfuscated "source code"
is not real source code and does not count as source code.
.Pp
Freedom 1 includes the freedom to use your changed version in place of the original. If the program
is delivered in a product designed to run someone else's modified versions but refuse to run yours--
a practice known as "tivoization" or "lockdown", or (in its practitioners' perverse terminology) as
"secure boot"-- freedom 1 becomes an empty pretense rather than a practical reality. These binaries
are not free software even if the source code they are compiled from is free.
.Pp
One important way to modify a program is by merging in available free subroutines and modules. If the
program's license says that you cannot merge in a suitably licensed existing module ? for instance,
if it requires you to be the copyright holder of any code you add ? then the license is too restrictive
to qualify as free.
.Pp
Freedom 3 includes the freedom to release your modified versions as free software. A free license may
also permit other ways of releasing them; in other words, it does not have to be a copyleft license.
However, a license that requires modified versions to be nonfree does not qualify as a free license.
.Pp
In order for these freedoms to be real, they must be permanent and irrevocable as long as you do
nothing wrong; if the developer of the software has the power to revoke the license, or retroactively
add restrictions to its terms, without your doing anything wrong to give cause, the software is not free.
.Pp
However, certain kinds of rules about the manner of distributing free software are acceptable, when
they don't conflict with the central freedoms. For example, copyleft (very simply stated) is the rule
that when redistributing the program, you cannot add restrictions to deny other people the central
freedoms. This rule does not conflict with the central freedoms; rather it protects them.
.Pp
In the GNU project, we use copyleft to protect the four freedoms legally for everyone. We believe there
are important reasons why it is better to use copyleft. However, noncopylefted free software is ethical
too. See Categories of Free Software for a description of how "free software," "copylefted software"
and other categories of software relate to each other.
.Pp
"Free software" does not mean "noncommercial". A free program must be available for commercial use,
commercial development, and commercial distribution. Commercial development of free software is no
longer unusual; such free commercial software is very important. You may have paid money to get copies
of free software, or you may have obtained copies at no charge. But regardless of how you got your copies,
you always have the freedom to copy and change the software, even to sell copies.
.Pp
Whether a change constitutes an improvement is a subjective matter. If your right to modify a program is
limited, in substance, to changes that someone else considers an improvement, that program is not free.
.Pp
However, rules about how to package a modified version are acceptable, if they don't substantively limit
your freedom to release modified versions, or your freedom to make and use modified versions privately.
Thus, it is acceptable for the license to require that you change the name of the modified version,
remove a logo, or identify your modifications as yours. As long as these requirements are not so
burdensome that they effectively hamper you from releasing your changes, they are acceptable; you're
already making other changes to the program, so you won't have trouble making a few more.
.Pp
Rules that "if you make your version available in this way, you must make it available in that way also"
can be acceptable too, on the same condition. An example of such an acceptable rule is one saying that
if you have distributed a modified version and a previous developer asks for a copy of it, you must send
one. (Note that such a rule still leaves you the choice of whether to distribute your version at all.)
Rules that require release of source code to the users for versions that you put into public use are
also acceptable.
.Pp
A special issue arises when a license requires changing the name by which the program will be invoked
from other programs. That effectively hampers you from releasing your changed version so that it can
replace the original when invoked by those other programs. This sort of requirement is acceptable only
if there's a suitable aliasing facility that allows you to specify the original program's name as an
alias for the modified version.
.Pp
Sometimes government export control regulations and trade sanctions can constrain your freedom to
distribute copies of programs internationally. Software developers do not have the power to eliminate
or override these restrictions, but what they can and must do is refuse to impose them as conditions
of use of the program. In this way, the restrictions will not affect activities and people outside the
jurisdictions of these governments. Thus, free software licenses must not require obedience to any
nontrivial export regulations as a condition of exercising any of the essential freedoms.
.Pp
Merely mentioning the existence of export regulations, without making them a condition of the license
itself, is acceptable since it does not restrict users. If an export regulation is actually trivial
for free software, then requiring it as a condition is not an actual problem; however, it is a potential
problem, since a later change in export law could make the requirement nontrivial and thus render the
software nonfree.
.Pp
A free license may not require compliance with the license of a nonfree program. Thus, for instance,
if a license requires you to comply with the licenses of "all the programs you use", in the case of a
user that runs nonfree programs this would require compliance with the licenses of those nonfree programs;
that makes the license nonfree.
.Pp
It is acceptable for a free license to specify which jurisdiction's law applies, or where litigation must
be done, or both.
.Pp
Most free software licenses are based on copyright, and there are limits on what kinds of requirements can
be imposed through copyright. If a copyright-based license respects freedom in the ways described above, it
is unlikely to have some other sort of problem that we never anticipated (though this does happen
occasionally). However, some free software licenses are based on contracts, and contracts can impose a much
larger range of possible restrictions. That means there are many possible ways such a license could be
unacceptably restrictive and nonfree.
.Pp
We can't possibly list all the ways that might happen. If a contract-based license restricts the user in
an unusual way that copyright-based licenses cannot, and which isn't mentioned here as legitimate, we
will have to think about it, and we will probably conclude it is nonfree.
.Pp
When talking about free software, it is best to avoid using terms like "give away" or "for free," because
those terms imply that the issue is about price, not freedom. Some common terms such as "piracy" embody
opinions we hope you won't endorse. See Confusing Words and Phrases that are Worth Avoiding for a discussion
of these terms. We also have a list of proper translations of "free software" into various languages.
.Pp
Finally, note that criteria such as those stated in this free software definition require careful thought
for their interpretation. To decide whether a specific software license qualifies as a free software license,
we judge it based on these criteria to determine whether it fits their spirit as well as the precise words.
If a license includes unconscionable restrictions, we reject it, even if we did not anticipate the issue
in these criteria. Sometimes a license requirement raises an issue that calls for extensive thought,
including discussions with a lawyer, before we can decide if the requirement is acceptable. When we reach
a conclusion about a new issue, we often update these criteria to make it easier to see why certain
licenses do or don't qualify. [...]
.Pp
.Sh LICENSE
The above is an except from the GNU essay "What's Free Software?" licensed under the CC BY-ND 4.0.
.Sh SEE ALSO
.Xr fsdg 7

.Sh HISTORY
The free-software(7) page appeared in LibertyBSD 5.9.


code:
.Dd $Mdocdate: April 16 2016 $
.Dt FSDG 7
.Os
.Sh NAME
.Nm fsdg
.Nd free software distribution guidelines

.Sh DESCRIPTION
The Free Software Distribution Guidelines (GNU FSDG) are
a set of guidelines put in place by the Free Software Foundation
to define what is required for an operating system to respect the
user's freedom and be considered a fully free operating system.
The LibertyBSD project strives to be fully Free Software and follow these
guidelines.

.Sh GUIDELINES
Summarized, fully free distributions must be:
.Bl -enum
.It
Self-hosting
.It
Fully Free Software
.It
Containing only free functional data and documentation
.It
Deblobbed of non-free firmware
.It
Unhindered in excerising the four freedoms by trademark law
.It
Without DRM, back-doors, and spyware
.It
Committed to correcting mistakes
.It
Actively maintained
.It
Without a misleading name
.El

.Sh SEE ALSO
.Xr free-software 7

.Sh HISTORY
The fsdg(7) page appeared in LibertyBSD 5.9.