Merge branch 'master' of github.com:evilsocket/pwnagotchi

This commit is contained in:
Simone Margaritelli 2019-11-13 00:11:59 +01:00
commit 9dcc647656
7 changed files with 222 additions and 6 deletions

View File

@ -32,6 +32,8 @@ class Agent(Client, Automata, AsyncAdvertiser, AsyncTrainer):
self._started_at = time.time()
self._filter = None if config['main']['filter'] is None else re.compile(config['main']['filter'])
self._current_channel = 0
self._tot_aps = 0
self._aps_on_channel = 0
self._supported_channels = utils.iface_channels(config['main']['iface'])
self._view = view
self._view.set_agent(self)
@ -187,6 +189,15 @@ class Agent(Client, Automata, AsyncAdvertiser, AsyncTrainer):
aps.sort(key=lambda ap: ap['channel'])
return self.set_access_points(aps)
def get_total_aps(self):
return self._tot_aps
def get_aps_on_channel(self):
return self._aps_on_channel
def get_current_channel(self):
return self._current_channel
def get_access_points_by_channel(self):
aps = self.get_access_points()
channels = self._config['personality']['channels']
@ -223,16 +234,16 @@ class Agent(Client, Automata, AsyncAdvertiser, AsyncTrainer):
# self._view.set('epoch', '%04d' % self._epoch.epoch)
def _update_counters(self):
tot_aps = len(self._access_points)
self._tot_aps = len(self._access_points)
tot_stas = sum(len(ap['clients']) for ap in self._access_points)
if self._current_channel == 0:
self._view.set('aps', '%d' % tot_aps)
self._view.set('aps', '%d' % self._tot_aps)
self._view.set('sta', '%d' % tot_stas)
else:
aps_on_channel = len([ap for ap in self._access_points if ap['channel'] == self._current_channel])
self._aps_on_channel = len([ap for ap in self._access_points if ap['channel'] == self._current_channel])
stas_on_channel = sum(
[len(ap['clients']) for ap in self._access_points if ap['channel'] == self._current_channel])
self._view.set('aps', '%d (%d)' % (aps_on_channel, tot_aps))
self._view.set('aps', '%d (%d)' % (self._aps_on_channel, self._tot_aps))
self._view.set('sta', '%d (%d)' % (stas_on_channel, tot_stas))
def _update_handshakes(self, new_shakes=0):

View File

@ -58,6 +58,9 @@ class Display(View):
def is_waveshare213d(self):
return self._implementation.name == 'waveshare213d'
def is_spotpear24inch(self):
return self._implementation.name == 'spotpear24inch'
def is_waveshare_any(self):
return self.is_waveshare_v1() or self.is_waveshare_v2()

View File

@ -9,7 +9,7 @@ from pwnagotchi.ui.hw.waveshare27inch import Waveshare27inch
from pwnagotchi.ui.hw.waveshare29inch import Waveshare29inch
from pwnagotchi.ui.hw.waveshare154inch import Waveshare154inch
from pwnagotchi.ui.hw.waveshare213d import Waveshare213d
from pwnagotchi.ui.hw.spotpear24inch import Spotpear24inch
def display_for(config):
# config has been normalized already in utils.load_config
@ -44,4 +44,7 @@ def display_for(config):
return Waveshare154inch(config)
elif config['ui']['display']['type'] == 'waveshare213d':
return Waveshare213d(config)
return Waveshare213d(config)
elif config['ui']['display']['type'] == 'spotpear24inch':
return Spotpear24inch(config)

View File

View File

@ -0,0 +1,144 @@
FBIOGET_VSCREENINFO=0x4600
FBIOPUT_VSCREENINFO=0x4601
FBIOGET_FSCREENINFO=0x4602
FBIOGETCMAP=0x4604
FBIOPUTCMAP=0x4605
FBIOPAN_DISPLAY=0x4606
FBIOGET_CON2FBMAP=0x460F
FBIOPUT_CON2FBMAP=0x4610
FBIOBLANK=0x4611
FBIO_ALLOC=0x4613
FBIO_FREE=0x4614
FBIOGET_GLYPH=0x4615
FBIOGET_HWCINFO=0x4616
FBIOPUT_MODEINFO=0x4617
FBIOGET_DISPINFO=0x4618
from mmap import mmap
from fcntl import ioctl
import struct
mm = None
bpp, w, h = 0, 0, 0 # framebuffer bpp and size
bytepp = 0
vx, vy, vw, vh = 0, 0, 0, 0 #virtual window offset and size
vi, fi = None, None
_fb_cmap = 'IIPPPP' # start, len, r, g, b, a
RGB = False
_verbose = False
msize_kb = 0
def report_fb(i=0, layer=0):
with open('/dev/fb'+str(i), 'r+b')as f:
vi = ioctl(f, FBIOGET_VSCREENINFO, bytes(160))
vi = list(struct.unpack('I'*40, vi))
ffm = 'c'*16+'L'+'I'*4+'H'*3+'ILIIHHH'
fic = struct.calcsize(ffm)
fi = struct.unpack(ffm, ioctl(f, FBIOGET_FSCREENINFO, bytes(fic)))
def ready_fb(_bpp=None, i=0, layer=0, _win=None):
global mm, bpp, w, h, vi, fi, RGB, msize_kb, vx, vy, vw, vh, bytepp
if mm and bpp == _bpp: return mm, w, h, bpp
with open('/dev/fb'+str(i), 'r+b')as f:
vi = ioctl(f, FBIOGET_VSCREENINFO, bytes(160))
vi = list(struct.unpack('I'*40, vi))
bpp = vi[6]
bytepp = bpp//8
if _bpp:
vi[6] = _bpp # 24 bit = BGR 888 mode
try:
vi = ioctl(f, FBIOPUT_VSCREENINFO, struct.pack('I'*40, *vi)) # fb_var_screeninfo
vi = struct.unpack('I'*40,vi)
bpp = vi[6]
bytepp = bpp//8
except:
pass
if vi[8] == 0 : RGB = True
ffm = 'c'*16+'L'+'I'*4+'H'*3+'ILIIHHH'
fic = struct.calcsize(ffm)
fi = struct.unpack(ffm, ioctl(f, FBIOGET_FSCREENINFO, bytes(fic)))
msize = fi[17] # = w*h*bpp//8
ll, start = fi[-7:-5]
w, h = ll//bytepp, vi[1] # when screen is vertical, width becomes wrong. ll//3 is more accurate at such time.
if _win and len(_win)==4: # virtual window settings
vx, vy, vw, vh = _win
if vw == 'w': vw = w
if vh == 'h': vh = h
vx, vy, vw, vh = map(int, (vx, vy, vw, vh))
if vx>=w: vx = 0
if vy>=h: vy = 0
if vx>w: vw = w - vx
else: vw -= vx
if vy>h: vh = h - vy
else: vh -= vy
else:
vx, vy, vw, vh = 0,0,w,h
msize_kb = vw*vh*bytepp//1024 # more accurate FB memory size in kb
mm = mmap(f.fileno(), msize, offset=start)
return mm, w, h, bpp#ll//(bpp//8), h
def fill_scr(r,g,b):
if bpp == 32:
seed = struct.pack('BBBB', b, g, r, 255)
elif bpp == 24:
seed = struct.pack('BBB', b, g, r)
elif bpp == 16:
seed = struct.pack('H', r>>3<<11 | g>>2<<5 | b>>3)
mm.seek(0)
show_img(seed * vw * vh)
def black_scr():
fill_scr(0,0,0)
def white_scr():
fill_scr(255,255,255)
def mmseekto(x,y):
mm.seek((x + y*w) * bytepp)
def dot(x, y, r, g, b):
mmseekto(x,y)
mm.write(struct.pack('BBB',*((r,g,b) if RGB else (b,g,r))))
def get_pixel(x,y):
mmseekto(x,y)
return mm.read(bytepp)
def _888_to_565(bt):
b = b''
for i in range(0, len(bt),3):
b += int.to_bytes(bt[i]>>3<<11|bt[i+1]>>2<<5|bt[i+2]>>3, 2, 'little')
return b
def numpy_888_565(bt):
import numpy as np
arr = np.fromstring(bt, dtype=np.uint32)
return (((0xF80000 & arr)>>8)|((0xFC00 & arr)>>5)|((0xF8 & arr)>>3)).astype(np.uint16).tostring()
def show_img(img):
if not type(img) is bytes:
if not RGB:
if bpp == 24: # for RPI
img = img.tobytes('raw', 'BGR')
else:
img = img.convert('RGBA').tobytes('raw', 'BGRA')
if bpp == 16:
img = numpy_888_565(img)
else:
if bpp == 24:
img = img.tobytes()
else:
img = img.convert('RGBA').tobytes()
if bpp == 16:
img = numpy_888_565(img)
from io import BytesIO
b = BytesIO(img)
s = vw*bytepp
for y in range(vh): # virtual window drawing
mmseekto(vx,vy+y)
mm.write(b.read(s))

View File

@ -0,0 +1,52 @@
import logging
import pwnagotchi.ui.fonts as fonts
from pwnagotchi.ui.hw.base import DisplayImpl
import os,time
class Spotpear24inch(DisplayImpl):
def __init__(self, config):
super(Spotpear24inch, self).__init__(config, 'spotpear24inch')
self._display = None
def layout(self):
fonts.setup(12, 10, 12, 70)
self._layout['width'] = 320
self._layout['height'] = 240
self._layout['face'] = (35, 50)
self._layout['name'] = (5, 20)
self._layout['channel'] = (0, 0)
self._layout['aps'] = (40, 0)
self._layout['uptime'] = (240, 0)
self._layout['line1'] = [0, 14, 320, 14]
self._layout['line2'] = [0, 220, 320, 220]
self._layout['friend_face'] = (0, 130)
self._layout['friend_name'] = (40, 135)
self._layout['shakes'] = (0, 220)
self._layout['mode'] = (280, 220)
self._layout['status'] = {
'pos': (80, 160),
'font': fonts.Medium,
'max': 20
}
return self._layout
def refresh(self):
time.sleep(0.1)
def initialize(self):
from pwnagotchi.ui.hw.libs.fb import fb
self._display = fb
logging.info("initializing spotpear 24inch lcd display")
self._display.ready_fb(i=1)
self._display.black_scr()
def render(self, canvas):
self._display.show_img(canvas.rotate(180))
self.refresh()
def clear(self):
self._display.black_scr()
self.refresh()

View File

@ -112,6 +112,9 @@ def load_config(args):
elif config['ui']['display']['type'] in ('ws_213d', 'ws213d', 'waveshare_213d', 'waveshare213d'):
config['ui']['display']['type'] = 'waveshare213d'
elif config['ui']['display']['type'] in ('spotpear24inch'):
config['ui']['display']['type'] = 'spotpear24inch'
else:
print("unsupported display type %s" % config['ui']['display']['type'])
exit(1)