def on_serial_scan(self, *args):
     """
     Update available serial ports
     """                                                                         
     if self.warnings.get():
         if not askyesno('Warning', 'This will attempt to open and close all serial ports on this system.  This has the potential to reset devices connected to the serial port.  Do you wish to proceed?'):
             return
     self.log.write('Scanning for available serial ports...')
     comports = sscan.scan()
     self.log.write('SUCCESS\n')
     if comports:
         for comport in comports:
             self.log.write("%s\n" % comport)
     else:
         self.log.write('No available serial ports.\n')
     self.comport.update(comports)
 def make_widgets(self):
     """
     Creates and packs the GUI widgets
     """
     self.widgets = []
     
     # Top level frames
     options_frame = Frame(self)
     options_frame.pack(side=TOP, padx=5, pady=5, expand=YES, fill=BOTH)
     
     status_frame = Frame(self)
     status_frame.pack(side=TOP, padx=5, pady=5, expand=YES, fill=BOTH)
     
     button_frame = Frame(self)
     button_frame.pack(side=TOP, padx=5, pady=5, expand=YES, fill=BOTH)
     
     # Options notebook and notebook tabs
     notebook = Notebook(options_frame)
     notebook.pack(side=TOP, padx=5, pady=5)
     
     serial_frame = Frame(notebook)
     notebook.add(serial_frame, text='Serial Port')
     
     firmware_frame = Frame(notebook)
     notebook.add(firmware_frame, text='Firmware')
     
     bsl_frame = Frame(notebook)
     notebook.add(bsl_frame, text='BSL')
     
     upload_frame = Frame(notebook)
     notebook.add(upload_frame, text='Upload')
     
     actions_frame = Frame(notebook)
     notebook.add(actions_frame, text='Actions')
     
     exit_frame = Frame(notebook)
     notebook.add(exit_frame, text='On Exit')
     
     # Serial Port Options
     self.comport = ComboSelector(serial_frame, 'Device', sscan.scan(), var=self.v_comport)
     self.widgets.append(self.comport)
     self.comport.pack(side=TOP, anchor=W, padx=5, pady=5, fill=X)
     
     self.speed = ComboSelector(serial_frame, 'Baud Rate', BAUDS, var=self.v_speed)
     self.widgets.append(self.speed)
     self.speed.pack(side=TOP, anchor=W, padx=5, pady=5, fill=X)
     
     self.invertrst = CheckButton(serial_frame, 'Invert RESET', var=self.v_invertrst)
     self.widgets.append(self.invertrst)
     self.invertrst.pack(side=TOP, anchor=W, padx=5, pady=5)
     
     self.inverttest = CheckButton(serial_frame, 'Invert TEST', var=self.v_inverttest)
     self.widgets.append(self.inverttest)
     self.inverttest.pack(side=TOP, anchor=W, padx=5, pady=5)
     
     self.swapresettest = CheckButton(serial_frame, 'Swap RESET and TEST', var=self.v_swapresettest)
     self.widgets.append(self.swapresettest)
     self.swapresettest.pack(side=TOP, anchor=W, padx=5, pady=5)
     
     self.testontx = CheckButton(serial_frame, 'TEST Toggles TX', var=self.v_testontx)
     self.widgets.append(self.testontx)
     # self.testontx.pack(side=TOP, anchor=W, padx=5, pady=5) # FIXME currently disabled, please see release notes
     
     self.slowmode = CheckButton(serial_frame, 'Slow Mode', var=self.v_slowmode)
     self.widgets.append(self.slowmode)
     self.slowmode.pack(side=TOP, anchor=W, padx=5, pady=5)
     
     self.timeout = IntEntry(serial_frame, 'Timeout', var=self.v_timeout)
     self.widgets.append(self.timeout)
     self.timeout.pack(side=TOP, anchor=W, padx=5, pady=5, fill=X)
     
     # Firmware Options
     self.filename = OpenFileEntry(firmware_frame, 'Input File', var=self.v_filename, filetypes=FIRMWARE_FILE_TYPES, initialdir=FILEINIDIR)
     self.widgets.append(self.filename)
     self.filename.pack(side=TOP, anchor=W, padx=5, pady=5, fill=X)
     
     self.filetype = RadioSelect(firmware_frame, 'File Type', FILE_TYPES, var=self.v_filetype)
     self.widgets.append(self.filetype)
     self.filetype.pack(side=TOP, anchor=W, padx=10, pady=5)
     
     self.cpu = RadioSelect(firmware_frame, 'CPU Family', CPU_TYPES, var=self.v_cpu)
     self.widgets.append(self.cpu)
     self.cpu.pack(side=TOP, anchor=W, padx=10, pady=5)
     
     # BSL Options
     self.password = OpenFileEntry(bsl_frame, 'Password File', var=self.v_password, filetypes=FIRMWARE_FILE_TYPES, initialdir=FILEINIDIR)
     self.widgets.append(self.password)
     self.password.pack(anchor=NW, padx=5, pady=5, fill=X)
     
     self.bslfile = OpenFileEntry(bsl_frame, 'BSL File', var=self.v_bslfile, filetypes=FIRMWARE_FILE_TYPES, initialdir=FILEINIDIR)
     self.widgets.append(self.bslfile)
     self.bslfile.pack(anchor=NW, padx=5, pady=5, fill=X)
     
     self.unpatched = CheckButton(bsl_frame, 'Leave BSL Unpatched', var=self.v_unpatched)
     self.widgets.append(self.unpatched)
     self.unpatched.pack(anchor=NW, padx=5, pady=5)
     
     self.ignoreanswer = CheckButton(bsl_frame, 'Ignore BSL Responses', var=self.v_ignoreanswer)
     self.widgets.append(self.ignoreanswer)
     self.ignoreanswer.pack(anchor=NW, padx=5, pady=5)
     
     self.nodownloadbsl = CheckButton(bsl_frame, 'No BSL Download', var=self.v_nodownloadbsl)
     self.widgets.append(self.nodownloadbsl)
     self.nodownloadbsl.pack(anchor=NW, padx=5, pady=5)
     
     self.forcebsl = CheckButton(bsl_frame, 'Force BSL Download', var=self.v_forcebsl)
     self.widgets.append(self.forcebsl)
     self.forcebsl.pack(anchor=NW, padx=5, pady=5)
     
     self.framesize = IntEntry(bsl_frame, 'Frame Size', var=self.v_framesize)
     self.widgets.append(self.framesize)
     self.framesize.pack(anchor=NW, padx=5, pady=5, fill=X)
     
     self.erasecycles = IntEntry(bsl_frame, 'Mass Erase Cycles', var=self.v_erasecycles)
     self.widgets.append(self.erasecycles)
     self.erasecycles.pack(anchor=NW, padx=5, pady=5, fill=X)
     
     # Upload Options
     self.startaddr = IntEntry(upload_frame, 'Upload Block Address', var=self.v_startaddr)
     self.widgets.append(self.startaddr)
     self.startaddr.pack(anchor=NW, padx=5, pady=5, fill=X)
     
     self.size = IntEntry(upload_frame, 'Upload Block Size', var=self.v_size)
     self.widgets.append(self.size)
     self.size.pack(anchor=NW, padx=5, pady=5, fill=X)
     
     self.outputformat = RadioSelect(upload_frame, 'Upload Format', UPLOAD_FORMATS, var=self.v_outputformat)
     self.widgets.append(self.outputformat)
     self.outputformat.pack(anchor=NW, padx=10, pady=5)
     
     self.uploadfile = SaveAsFileEntry(upload_frame, 'Save Upload Directly To File', var=self.v_uploadfile, filetypes=FIRMWARE_FILE_TYPES, initialdir=FILEINIDIR)
     self.widgets.append(self.uploadfile)
     self.uploadfile.pack(anchor=NW, padx=5, pady=5, fill=X)
     
     # Actions Options
     self.masserase = CheckButton(actions_frame, 'Erase All Flash Memory', var=self.v_masserase)
     self.widgets.append(self.masserase)
     self.masserase.pack(side=TOP, anchor=W, padx=5, pady=5)
     
     self.mainerase = CheckButton(actions_frame, 'Erase Main Flash Memory', var=self.v_mainerase)
     self.widgets.append(self.mainerase)
     self.mainerase.pack(side=TOP, anchor=W, padx=5, pady=5) # requires password to be set
     
     self.erase = IntRangeEntry(actions_frame, 'Erase segment or segment range', var=self.v_erase)
     self.widgets.append(self.erase)
     self.erase.pack(side=TOP, anchor=W, padx=5, pady=5, fill=X) # requires password to be set
     
     self.erasecheck = CheckButton(actions_frame, 'Erase Check By File', var=self.v_erasecheck)
     self.widgets.append(self.erasecheck)
     self.erasecheck.pack(side=TOP, anchor=W, padx=5, pady=5)
     
     self.program = CheckButton(actions_frame, 'Program File', var=self.v_program)
     self.widgets.append(self.program)
     self.program.pack(side=TOP, anchor=W, padx=5, pady=5)
     
     self.verify = CheckButton(actions_frame, 'Verify', var=self.v_verify)
     self.widgets.append(self.verify)
     self.verify.pack(side=TOP, anchor=W, padx=5, pady=5)
     
     self.bslversion = CheckButton(actions_frame, 'Read BSL Version', var=self.v_bslversion)
     self.widgets.append(self.bslversion)
     self.bslversion.pack(anchor=NW, padx=5, pady=5)
     
     # On Exit Options
     self.goaddr = IntEntry(exit_frame, 'Start Execution Address', var=self.v_goaddr)
     self.widgets.append(self.goaddr)
     self.goaddr.pack(anchor=NW, padx=5, pady=5, fill=X) #Implies wait
     
     self.wait = CheckButton(exit_frame, 'Wait', var=self.v_wait)
     self.widgets.append(self.wait)
     self.wait.pack(anchor=NW, padx=5, pady=5)
     
     self.reset = CheckButton(exit_frame, 'Reset', var=self.v_reset)
     self.widgets.append(self.reset)
     self.reset.pack(anchor=NW, padx=5, pady=5)
     
     # Progress Bar
     self.progressbar = ProgressBar(status_frame, 'BSL Progress...', var=self.v_progress, length=200)
     self.widgets.append(self.progressbar)
     self.progressbar.pack(side=TOP)
     
     # Buttons
     Button(button_frame, text='Defaults', command=self.set_defaults).pack(side=LEFT, anchor=W, padx=5, pady=5)
     Button(button_frame, text='Scan', command=self.on_serial_scan).pack(side=LEFT, anchor=W, padx=0, pady=5)
     Button(button_frame, text='Go', command=self.on_go).pack(side=RIGHT, anchor=E, padx=5, pady=5)