1 /* 2 * Copyright 2012, Adrien Destugues, pulkomandy@gmail.com 3 * Distributed under the terms of the MIT licence. 4 */ 5 6 7 #include "SerialWindow.h" 8 9 #include <stdio.h> 10 11 #include <FilePanel.h> 12 #include <GroupLayout.h> 13 #include <Menu.h> 14 #include <MenuBar.h> 15 #include <MenuItem.h> 16 #include <SerialPort.h> 17 18 #include "SerialApp.h" 19 #include "TermView.h" 20 21 22 SerialWindow::SerialWindow() 23 : BWindow(BRect(100, 100, 400, 400), SerialWindow::kWindowTitle, 24 B_DOCUMENT_WINDOW, B_QUIT_ON_WINDOW_CLOSE | B_AUTO_UPDATE_SIZE_LIMITS) 25 , fLogFilePanel(NULL) 26 { 27 SetLayout(new BGroupLayout(B_VERTICAL, 0.0f)); 28 29 BMenuBar* menuBar = new BMenuBar("menuBar"); 30 fTermView = new TermView(); 31 32 AddChild(menuBar); 33 AddChild(fTermView); 34 35 fConnectionMenu = new BMenu("Connection"); 36 BMenu* fileMenu = new BMenu("File"); 37 BMenu* settingsMenu = new BMenu("Settings"); 38 39 fConnectionMenu->SetRadioMode(true); 40 41 menuBar->AddItem(fConnectionMenu); 42 menuBar->AddItem(fileMenu); 43 menuBar->AddItem(settingsMenu); 44 45 // TODO edit menu - what's in it ? 46 //BMenu* editMenu = new BMenu("Edit"); 47 //menuBar->AddItem(editMenu); 48 49 BMenuItem* logFile = new BMenuItem("Log to file" B_UTF8_ELLIPSIS, 50 new BMessage(kMsgLogfile)); 51 fileMenu->AddItem(logFile); 52 BMenuItem* xmodemSend = new BMenuItem("X/Y/ZModem send" B_UTF8_ELLIPSIS, 53 NULL); 54 fileMenu->AddItem(xmodemSend); 55 BMenuItem* xmodemReceive = new BMenuItem( 56 "X/Y/Zmodem receive" B_UTF8_ELLIPSIS, NULL); 57 fileMenu->AddItem(xmodemReceive); 58 59 // Configuring all this by menus may be a bit unhandy. Make a setting 60 // window instead ? 61 BMenu* baudRate = new BMenu("Baud rate"); 62 baudRate->SetRadioMode(true); 63 settingsMenu->AddItem(baudRate); 64 65 BMenu* parity = new BMenu("Parity"); 66 parity->SetRadioMode(true); 67 settingsMenu->AddItem(parity); 68 69 BMenu* stopBits = new BMenu("Stop bits"); 70 stopBits->SetRadioMode(true); 71 settingsMenu->AddItem(stopBits); 72 73 BMenu* flowControl = new BMenu("Flow control"); 74 flowControl->SetRadioMode(true); 75 settingsMenu->AddItem(flowControl); 76 77 BMenu* dataBits = new BMenu("Data bits"); 78 dataBits->SetRadioMode(true); 79 settingsMenu->AddItem(dataBits); 80 81 82 BMessage* message = new BMessage(kMsgSettings); 83 message->AddInt32("parity", B_NO_PARITY); 84 BMenuItem* parityNone = new BMenuItem("None", message); 85 86 message = new BMessage(kMsgSettings); 87 message->AddInt32("parity", B_ODD_PARITY); 88 BMenuItem* parityOdd = new BMenuItem("Odd", message); 89 90 message = new BMessage(kMsgSettings); 91 message->AddInt32("parity", B_EVEN_PARITY); 92 BMenuItem* parityEven = new BMenuItem("Even", message); 93 parityNone->SetMarked(true); 94 95 parity->AddItem(parityNone); 96 parity->AddItem(parityOdd); 97 parity->AddItem(parityEven); 98 parity->SetTargetForItems(be_app); 99 100 message = new BMessage(kMsgSettings); 101 message->AddInt32("databits", B_DATA_BITS_7); 102 BMenuItem* data7 = new BMenuItem("7", message); 103 104 message = new BMessage(kMsgSettings); 105 message->AddInt32("databits", B_DATA_BITS_8); 106 BMenuItem* data8 = new BMenuItem("8", message); 107 data8->SetMarked(true); 108 109 dataBits->AddItem(data7); 110 dataBits->AddItem(data8); 111 dataBits->SetTargetForItems(be_app); 112 113 message = new BMessage(kMsgSettings); 114 message->AddInt32("stopbits", B_STOP_BITS_1); 115 BMenuItem* stop1 = new BMenuItem("1", NULL); 116 117 message = new BMessage(kMsgSettings); 118 message->AddInt32("stopbits", B_STOP_BITS_2); 119 BMenuItem* stop2 = new BMenuItem("2", NULL); 120 stop1->SetMarked(true); 121 122 stopBits->AddItem(stop1); 123 stopBits->AddItem(stop2); 124 stopBits->SetTargetForItems(be_app); 125 126 static const int baudrates[] = { 50, 75, 110, 134, 150, 200, 300, 600, 127 1200, 1800, 2400, 4800, 9600, 19200, 31250, 38400, 57600, 115200, 128 230400 129 }; 130 131 // Loop backwards to add fastest rates at top of menu 132 for (int i = sizeof(baudrates) / sizeof(char*); --i >= 0;) 133 { 134 message = new BMessage(kMsgSettings); 135 message->AddInt32("baudrate", baudrates[i]); 136 137 char buffer[7]; 138 sprintf(buffer,"%d", baudrates[i]); 139 BMenuItem* item = new BMenuItem(buffer, message); 140 141 if (baudrates[i] == 19200) 142 item->SetMarked(true); 143 144 baudRate->AddItem(item); 145 } 146 147 baudRate->SetTargetForItems(be_app); 148 149 message = new BMessage(kMsgSettings); 150 message->AddInt32("flowcontrol", B_HARDWARE_CONTROL); 151 BMenuItem* hardware = new BMenuItem("Hardware", message); 152 hardware->SetMarked(true); 153 154 message = new BMessage(kMsgSettings); 155 message->AddInt32("flowcontrol", B_SOFTWARE_CONTROL); 156 BMenuItem* software = new BMenuItem("Software", message); 157 158 message = new BMessage(kMsgSettings); 159 message->AddInt32("flowcontrol", B_HARDWARE_CONTROL | B_SOFTWARE_CONTROL); 160 BMenuItem* both = new BMenuItem("Both", message); 161 162 message = new BMessage(kMsgSettings); 163 message->AddInt32("flowcontrol", 0); 164 BMenuItem* noFlow = new BMenuItem("None", message); 165 166 flowControl->AddItem(hardware); 167 flowControl->AddItem(software); 168 flowControl->AddItem(both); 169 flowControl->AddItem(noFlow); 170 flowControl->SetTargetForItems(be_app); 171 172 CenterOnScreen(); 173 } 174 175 176 177 SerialWindow::~SerialWindow() 178 { 179 delete fLogFilePanel; 180 } 181 182 183 void SerialWindow::MenusBeginning() 184 { 185 // remove all items from the menu 186 while(fConnectionMenu->RemoveItem(0L)); 187 188 // fill it with the (updated) serial port list 189 BSerialPort serialPort; 190 int deviceCount = serialPort.CountDevices(); 191 192 for(int i = 0; i < deviceCount; i++) 193 { 194 char buffer[256]; 195 serialPort.GetDeviceName(i, buffer, 256); 196 197 BMessage* message = new BMessage(kMsgOpenPort); 198 message->AddString("port name", buffer); 199 BMenuItem* portItem = new BMenuItem(buffer, message); 200 portItem->SetTarget(be_app); 201 202 fConnectionMenu->AddItem(portItem); 203 } 204 205 if (deviceCount > 0) { 206 fConnectionMenu->AddSeparatorItem(); 207 208 BMenuItem* disconnect = new BMenuItem("Disconnect", 209 new BMessage(kMsgOpenPort), 'Z', B_OPTION_KEY); 210 fConnectionMenu->AddItem(disconnect); 211 } else { 212 BMenuItem* noDevices = new BMenuItem("<no serial port available>", NULL); 213 noDevices->SetEnabled(false); 214 fConnectionMenu->AddItem(noDevices); 215 } 216 } 217 218 void SerialWindow::MessageReceived(BMessage* message) 219 { 220 switch(message->what) 221 { 222 case kMsgOpenPort: 223 { 224 BMenuItem* disconnectMenu; 225 if(message->FindPointer("source", (void**)&disconnectMenu) == B_OK) 226 disconnectMenu->SetMarked(false); 227 be_app->PostMessage(new BMessage(*message)); 228 break; 229 } 230 case kMsgDataRead: 231 { 232 const char* bytes; 233 ssize_t length; 234 message->FindData("data", B_RAW_TYPE, (const void**)&bytes, &length); 235 fTermView->PushBytes(bytes, length); 236 break; 237 } 238 case kMsgLogfile: 239 { 240 // Let's lazy init the file panel 241 if(fLogFilePanel == NULL) { 242 fLogFilePanel = new BFilePanel(B_SAVE_PANEL, &be_app_messenger, 243 NULL, B_FILE_NODE, false); 244 fLogFilePanel->SetMessage(message); 245 } 246 fLogFilePanel->Show(); 247 break; 248 } 249 default: 250 BWindow::MessageReceived(message); 251 } 252 } 253 254 255 const char* SerialWindow::kWindowTitle = "SerialConnect"; 256