The Pedigree Project  0.1
DevicesCommand.cc
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "pedigree/kernel/debugger/commands/DevicesCommand.h"
21 #include "pedigree/kernel/debugger/DebuggerIO.h"
22 #include "pedigree/kernel/machine/Device.h"
23 #include "pedigree/kernel/utilities/String.h"
24 #include "pedigree/kernel/utilities/utility.h"
25 
27 {
28 }
29 
31 {
32 }
33 
35  const HugeStaticString &input, HugeStaticString &output)
36 {
37 }
38 
40  const HugeStaticString &input, HugeStaticString &output,
41  InterruptState &state, DebuggerIO *pScreen)
42 {
43  // Let's enter 'raw' screen mode.
44  pScreen->disableCli();
45 
46  // Work out where the split will be between the tree and the info.
47  // Give the tree 3/4 of the available lines.
48  int nLines = ((pScreen->getHeight() - 2) * 3) / 4;
49 
50  static DeviceTree tree;
51  tree.move(0, 1);
52  tree.resize(pScreen->getWidth(), nLines);
53  tree.setScrollKeys('o', 'p');
54 
55  static DeviceInfo info;
56  info.move(0, nLines + 2);
57  info.resize(pScreen->getWidth(), pScreen->getHeight() - nLines - 3);
58  info.setScrollKeys('j', 'k');
59 
60  pScreen->disableRefreshes();
61  drawBackground(nLines, pScreen);
62  tree.refresh(pScreen);
63  info.refresh(pScreen);
64  pScreen->enableRefreshes();
65 
66  // Here we enter our main runloop.
67  bool bContinue = true;
68  while (bContinue)
69  {
70  char c;
71  while ((c = pScreen->getChar()) == 0)
72  ;
73  if (c == 'q')
74  break;
75  else if (c == 'o')
76  {
77  if (tree.m_Line > 0)
78  tree.m_Line--;
79  tree.centreOn(tree.m_Line);
80  tree.refresh(pScreen);
81  info.setDevice(tree.getDevForIndex(tree.m_Line));
82  info.refresh(pScreen);
83  }
84  else if (c == 'p')
85  {
86  if (tree.m_Line < tree.getLineCount() - 1)
87  tree.m_Line++;
88  tree.centreOn(tree.m_Line);
89  tree.refresh(pScreen);
90  info.setDevice(tree.getDevForIndex(tree.m_Line));
91  info.refresh(pScreen);
92  }
93  else if (c == 'j')
94  {
95  info.scroll(-1);
96  info.refresh(pScreen);
97  }
98  else if (c == 'k')
99  {
100  info.scroll(1);
101  info.refresh(pScreen);
102  }
103  else if (c == 'd')
104  {
105  // Dump.
106  String str;
107  info.getDevice()->dump(str);
108  drawBackground(0, pScreen);
109  pScreen->drawString(
110  "Querying device - press any key to exit. ", 1, 0,
111  DebuggerIO::White, DebuggerIO::Black);
112  pScreen->drawString(
113  str, 2, 0, DebuggerIO::LightGrey, DebuggerIO::Black);
114  while ((c = pScreen->getChar()) == 0)
115  ;
116  drawBackground(nLines, pScreen);
117  tree.refresh(pScreen);
118  info.refresh(pScreen);
119  }
120  }
121 
122  // Let's enter CLI screen mode again.
123  pScreen->enableCli();
124  return true; // Return control to the debugger.
125 }
126 
127 void DevicesCommand::drawBackground(size_t nLines, DebuggerIO *pScreen)
128 {
129  // Destroy all text.
130  pScreen->cls();
131 
132  // Clear the top and bottom status lines.
133  pScreen->drawHorizontalLine(
134  ' ', 0, 0, pScreen->getWidth() - 1, DebuggerIO::White,
135  DebuggerIO::Green);
136  pScreen->drawHorizontalLine(
137  ' ', pScreen->getHeight() - 1, 0, pScreen->getWidth() - 1,
138  DebuggerIO::White, DebuggerIO::Green);
139  // Write the correct text in the upper status line.
140  pScreen->drawString(
141  "Pedigree debugger - Device tree", 0, 0, DebuggerIO::White,
142  DebuggerIO::Green);
143  // Write some helper text in the lower status line.
144  pScreen->drawString(
145  "", pScreen->getHeight() - 1, 0, DebuggerIO::White, DebuggerIO::Green);
146 
147  pScreen->drawHorizontalLine(
148  '-', nLines + 1, 0, pScreen->getWidth(), DebuggerIO::DarkGrey,
149  DebuggerIO::Black);
150 }
151 
152 DevicesCommand::DeviceTree::DeviceTree() : m_Line(0), m_LinearTree()
153 {
154  // Create the (flattened) device tree, so we can look up the index of any
155  // particular device.
156  auto pusher = [this](Device *p) {
157  m_LinearTree.pushBack(p);
158  return p;
159  };
160 
161  auto callback = pedigree_std::make_callable(pusher);
162 
163  // Get the first device.
164  Device::foreach (callback, 0);
165 }
166 
167 void DevicesCommand::DeviceTree::probeDev(Device *pDev)
168 {
169  for (unsigned int i = 0; i < pDev->getNumChildren(); i++)
170  {
171  m_LinearTree.pushBack(pDev->getChild(i));
172  probeDev(pDev->getChild(i));
173  }
174 }
175 
176 const char *DevicesCommand::DeviceTree::getLine1(
177  size_t index, DebuggerIO::Colour &colour, DebuggerIO::Colour &bgColour)
178 {
179  static NormalStaticString str;
180 
181  // Grab the device to describe.
182  Device *pDev = m_LinearTree[index];
183 
184  // Set the foreground colour.
185  colour = DebuggerIO::Yellow;
186 
187  // If we're the selected line, add our background colour.
188  if (m_Line == index)
189  bgColour = DebuggerIO::Blue;
190 
191  // How many parents does this node have? that will determine how many |'s to
192  // draw.
193  while (pDev->getParent() != 0)
194  {
195  pDev = pDev->getParent();
196  str += " ";
197  }
198  str += "- ";
199 
200  return str;
201 }
202 
203 const char *DevicesCommand::DeviceTree::getLine2(
204  size_t index, size_t &colOffset, DebuggerIO::Colour &colour,
205  DebuggerIO::Colour &bgColour)
206 {
207  static LargeStaticString str;
208 
209  // Grab the device to describe.
210  Device *pDev = m_LinearTree[index];
211 
212  // Set the foreground colour.
213  colour = DebuggerIO::White;
214 
215  String str2;
216  pDev->getName(str2);
217  str += str2;
218  str += "(";
219  str += pDev->getSpecificType();
220  str += ")";
221 
222  // Calculate the column offset.
223  // How many parents does this node have? that will determine how many |'s to
224  // draw.
225  colOffset = 0;
226  while (pDev->getParent() != 0)
227  {
228  pDev = pDev->getParent();
229  colOffset++;
230  }
231  colOffset += 2; // For '- '
232 
233  // If we're selected, add our background colour and pad to the end-of-line.
234  if (m_Line == index)
235  {
236  bgColour = DebuggerIO::Blue;
237  }
238  str.pad(m_width - colOffset);
239 
240  return str;
241 }
242 
243 size_t DevicesCommand::DeviceTree::getLineCount()
244 {
245  return m_LinearTree.count();
246 }
247 
248 Device *DevicesCommand::DeviceTree::getDevForIndex(size_t index)
249 {
250  return m_LinearTree[index];
251 }
252 
253 DevicesCommand::DeviceInfo::DeviceInfo() : m_pDev(0)
254 {
255 }
256 
257 void DevicesCommand::DeviceInfo::setDevice(Device *dev)
258 {
259  m_pDev = dev;
260 }
261 
262 const char *DevicesCommand::DeviceInfo::getLine1(
263  size_t index, DebuggerIO::Colour &colour, DebuggerIO::Colour &bgColour)
264 {
265  colour = DebuggerIO::Yellow;
266  switch (index)
267  {
268  case 0:
269  return "Name";
270  case 1:
271  return "(Abstract) type";
272  case 2:
273  return "(Specific) type";
274  case 3:
275  return "Interrupt";
276  case 4:
277  return "Openfirmware Handle";
278  case 5:
279  return "Addresses";
280  default:
281  return "";
282  };
283 }
284 
285 const char *DevicesCommand::DeviceInfo::getLine2(
286  size_t index, size_t &colOffset, DebuggerIO::Colour &colour,
287  DebuggerIO::Colour &bgColour)
288 {
289  if (!m_pDev)
290  return "";
291  static LargeStaticString str;
292  colOffset = 40;
293  switch (index)
294  {
295  case 0:
296  {
297  String str2;
298  m_pDev->getName(str2);
299  str += str2;
300  break;
301  }
302  case 1:
303  str += static_cast<unsigned int>(m_pDev->getType());
304  break;
305  case 2:
306  str += m_pDev->getSpecificType();
307  break;
308  case 3:
309  str += m_pDev->getInterruptNumber();
310  break;
311  case 4:
312 #ifdef OPENFIRMWARE
313  str.append(reinterpret_cast<uintptr_t>(m_pDev->getOFHandle()), 16);
314  break;
315 #else
316  str += "Not applicable";
317  break;
318 #endif
319  default:
320  {
321  unsigned int i = index - 5;
322  if (i >= m_pDev->addresses().count())
323  break;
324  Device::Address *address = m_pDev->addresses()[i];
325  str += address->m_Name;
326  if (address->m_IsIoSpace)
327  str += " (IO) @ ";
328  else
329  str += " (MEM) @ ";
330  str.append(address->m_Address, 16);
331  str += "-";
332  str.append(address->m_Address + address->m_Size, 16);
333  break;
334  }
335  };
336  return str;
337 }
338 
339 size_t DevicesCommand::DeviceInfo::getLineCount()
340 {
341  if (m_pDev)
342  return 5 + m_pDev->addresses().count();
343  else
344  return 5;
345 }
virtual void dump(String &str)
Definition: Device.h:250
Device * getChild(size_t n)
Definition: Device.cc:132
uintptr_t m_Address
Definition: Device.h:89
virtual size_t getWidth()=0
virtual void enableCli()=0
size_t getNumChildren()
Definition: Device.cc:137
virtual void getName(String &str)
Definition: Device.cc:121
virtual String getSpecificType()
Definition: Device.h:169
String m_Name
Definition: Device.h:86
size_t m_Size
Definition: Device.h:91
virtual char getChar()=0
Definition: String.h:49
void autocomplete(const HugeStaticString &input, HugeStaticString &output)
Definition: Device.h:43
virtual void enableRefreshes()=0
bool m_IsIoSpace
Definition: Device.h:94
bool execute(const HugeStaticString &input, HugeStaticString &output, InterruptState &state, DebuggerIO *screen)
static void foreach(Callback callback, Device *root=0)
Definition: Device.cc:94
virtual void drawString(const char *str, size_t row, size_t col, Colour foreColour, Colour backColour)=0
virtual void drawHorizontalLine(char c, size_t row, size_t colStart, size_t colEnd, Colour foreColour, Colour backColour)=0
Device * getParent() const
Definition: Device.h:149