summaryrefslogtreecommitdiffstats
path: root/modules-available/passthrough/page.inc.php
blob: 3ab0696e3b6cbc16c42489fb1dbaa69296935796 (plain) (blame)
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
<?php

class Page_Passthrough extends Page
{

	protected function doPreprocess()
	{
		User::load();
		User::assertPermission('view');
		$action = Request::post('action');
		if ($action === 'save-hwlist') {
			$this->saveHwList();
		}
		if (Request::isPost()) {
			Util::redirect('?do=passthrough');
		}
	}

	private function saveHwList()
	{
		$newgroups = Request::post('newgroup', [], 'array');
		foreach ($newgroups as $id => $title) {
			$id = strtoupper(preg_replace('/[^a-z0-9_\-]/i', '', $id));
			if (empty($id))
				continue;
			Database::exec("INSERT IGNORE INTO passthrough_group (groupid, title)
				VALUES (:group, :title)",
				['group' => $id, 'title' => $title]);
		}
		$groups = Request::post('ptgroup', Request::REQUIRED, 'array');
		$insert = [];
		$delete = [];
		foreach ($groups as $hwid => $group) {
			if (empty($group)) {
				$delete[] = $hwid;
			} else {
				$insert[] = [$hwid, '@PASSTHROUGH', $group];
			}
		}
		if (!empty($insert)) {
			Database::exec("INSERT INTO statistic_hw_prop (hwid, prop, `value`) VALUES :list
				ON DUPLICATE KEY UPDATE `value` = VALUES(`value`)",
				['list' => $insert]);
		}
		if (!empty($delete)) {
			Database::exec("DELETE FROM statistic_hw_prop WHERE hwid IN (:list) AND prop = '@PASSTHROUGH'", ['list' => $delete]);
		}
		Message::addSuccess('list-updated');
		Util::redirect('?do=passthrough&show=hwlist');
	}

	/*
	 *
	 */

	protected function doRender()
	{
		$show = Request::get('show');
		if ($show === 'hwlist') {
			$this->showHardwareList();
		} else {
			Util::redirect('?do=passthrough&show=hwlist');
		}
	}

	private function showHardwareList()
	{
		$q = new HardwareQuery(HardwareInfo::PCI_DEVICE, null, false);
		$q->addGlobalColumn('vendor');
		$q->addGlobalColumn('device');
		$q->addGlobalColumn('class');
		$q->addGlobalColumn('@PASSTHROUGH');
		$rows = [];
		foreach ($q->query('shw.hwid') as $row) {
			$row['ptlist'] = Passthrough::getGroupDropdown($row);
			$rows[] = $row;
		}
		// Sort Graphics Cards first, rest by class, vendor, device
		usort($rows, function ($row1, $row2) {
			$a = $row1['class'];
			$b = $row2['class'];
			if ($a === $b)
				return hexdec($row1['vendor'].$row1['device']) - hexdec($row2['vendor'] . $row2['device']);
			if ($a === '0300')
				return -1;
			if ($b === '0300')
				return 1;
			return hexdec($a) - hexdec($b);
		});
		$finalRows = [];
		$missing = [];
		$lastClass = '';
		foreach ($rows as $row) {
			if ($row['class'] !== $lastClass) {
				// Add class row header
				$lastClass = $row['class'];
				$finalRows[] = [
					'class' => $row['class'],
					'class_name' => PciId::getPciId(PciId::DEVCLASS, $row['class'], true) ?: 'Unknown',
				];
			}
			$row['vendor_name'] = PciId::getPciId(PciId::VENDOR, $row['vendor'] ?? '');
			$row['device_name'] = PciId::getPciId(PciId::DEVICE, $row['vendor'] . ':' . $row['device']);
			$finalRows[] = $row;
			// Build up query
			if ($row['vendor_name'] === false) {
				$missing[$row['vendor']] = true;
			}
			if ($row['device_name'] === false) {
				$missing[$row['vendor'] . ':' . $row['device']] = true;
			}
		}
		Render::addTemplate('hardware-list', [
			'list' => $finalRows,
			'missing_ids' => json_encode(array_keys($missing)),
			]);
	}

	/*
	 *
	 */

	protected function doAjax()
	{
		//
	}

}