PageRenderTime 58ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/uClinux-dist/user/horch/horch.c

https://bitbucket.org/__wp__/mb-linux-msli
C | 1778 lines | 831 code | 87 blank | 860 comment | 163 complexity | bad54670c454e62678da0796ddda87b5 MD5 | raw file
Possible License(s): AGPL-3.0, GPL-2.0, LGPL-2.0, MPL-2.0, ISC, BSD-3-Clause, LGPL-2.1, MPL-2.0-no-copyleft-exception, 0BSD, CC-BY-SA-3.0, GPL-3.0, LGPL-3.0, AGPL-1.0, Unlicense
  1. /*
  2. *++ horch - simple CAN bus analyzer
  3. *-- horch - einfacher CAN Bus Analyzer
  4. *
  5. * Copyright (c) 1999-2001 port GmbH, Halle
  6. *------------------------------------------------------------------
  7. * $Header: /cvs/sw/new-wave/user/horch/horch.c,v 1.2 2007-04-04 05:20:33 gerg Exp $
  8. *
  9. *--------------------------------------------------------------------------
  10. *
  11. *
  12. * modification history
  13. * --------------------
  14. * $Log: horch.c,v $
  15. * Revision 1.2 2007-04-04 05:20:33 gerg
  16. * #10381
  17. *
  18. * Little changes to make horch listen to the CAN
  19. *
  20. * Patch submitted by Thomas Brinker <tb@emlix.com>
  21. *
  22. * Revision 1.1 2003/07/18 00:11:46 gerg
  23. * I followed as much rules as possible (I hope) and generated a patch for the
  24. * uClinux distribution. It contains an additional driver, the CAN driver, first
  25. * for an SJA1000 CAN controller:
  26. * uClinux-dist/linux-2.4.x/drivers/char/can4linux
  27. * In the "user" section two entries
  28. * uClinux-dist/user/can4linux some very simple test examples
  29. * uClinux-dist/user/horch more sophisticated CAN analyzer example
  30. *
  31. * Patch submitted by Heinz-Juergen Oertel <oe@port.de>.
  32. *
  33. *
  34. *
  35. */
  36. /*
  37. * SYNOPSIS
  38. *
  39. * .CS
  40. * \fBhorch\fR [dtSTV] [-D dev][-b baud][-c id][-l file][-p port]
  41. * .CE
  42. * .nf
  43. * .ta 1i
  44. * .nf
  45. *-- Aufrufargumente
  46. *++ Command line options
  47. * .CS
  48. *-- -a - advanced - benutzt \"baud\" als BTR0/1 Wert
  49. *-- -b baud - Baudrate für CAN (in KBit/s, Standard 125)
  50. *-- -c<id> - Benutzung der CAN id als Debug-ID
  51. *-- -d - Debug Mode, nützlich für Programmentwicklung
  52. *-- -f<spec> - Spezifikation für Empfangsfilter
  53. *-- -l<file> - Dateiname für lokales Aufzeichnen, Aktivierung mit 'l'
  54. *-- -p<n> - benutze Portnummer n im Servermode, Standard 7235
  55. *-- -t - Anzeige von Zeitstempeln beim Start
  56. *-- -C - interpretiere die -c CAN Message als Debug Message
  57. *-- -D device - CAN Geräte Name, (z.B can1 (LINUX); 0..2 (Level-X))
  58. *-- -S - TCP/IP Server Mode
  59. *-- -u - benutzt UDP
  60. *-- -T - Benutzen der Betriebssystemzeit statt Treiber-Zeit
  61. *-- -V - Version
  62. * .br
  63. *++ -a - advanced - use \"baud\" as BTR0/1 value
  64. *++ -b baud - use this baud rate at CAN (in KBit/s, Standard 125)
  65. *++ -c<id> - use id as debug id
  66. *++ -d - debug mode, useful for program developer
  67. *++ -f<spec> - specification for receive message filter
  68. *++ -l<file> - Logfilename, logging is enabled/disabled with 'l'
  69. *++ -p<n> - use portnumber in Servermode, default 7235
  70. *++ -t - show time stamp at start up
  71. *++ -C - interpret message id given with -c as debug message
  72. *++ -D device - CAN device Name, (z.B can1 (LINUX); 0..3 (Level-X Channel))
  73. *++ -S - TCP/IP Server Mode
  74. *++ -u - use UDP
  75. *++ -T - use OS time not drivers time stamp
  76. *++ -V - Version
  77. * .CE
  78. * .LP
  79. *.\".CS
  80. *--.\"zusätzlich beim EtherCAN
  81. *++.\"additional for EtherCAN
  82. *++.\" -C - occupy console focus
  83. *--.\" -C - Console Focus auf horch
  84. *.\".CE
  85. * .LP
  86. * .CS
  87. *-- zusätzlich beim LevelX
  88. *++ additional for LevelX
  89. *++ -B - board name (see horch -h)
  90. *++ -U - board number (e.g. 1..4 COM port)
  91. *-- -B - Board Name (siehe horch -h)
  92. *-- -U - Board Nummer (z.B. 1..4 COM Port)
  93. * .CE
  94. *
  95. *
  96. *++ DESCRIPTION
  97. *-- BESCHREIBUNG
  98. *
  99. * Version 2.4p1
  100. * .sp
  101. * .B horch
  102. *++ is a command line application that is capable of receiving
  103. *++ CAN messages and displaying them in a console window.
  104. *++ Because the receiving of CAN messages
  105. *++ depends on a special hardware, the application is divided in the two parts,
  106. *++ hardware dependend and console specific.
  107. *-- ist eine Kommandozeilen Anwendung die in der Lage ist, CAN Nachrichten
  108. *-- zu empfangen und in einem Konsolenfenster anzuzeigen.
  109. *-- Der Empfang von CAN Nachrichten ist hardwareabhängig.
  110. *-- Die
  111. *-- .B horch
  112. *-- Anwendung gliedert sich deshalb in zwei Teile,
  113. *-- einen hardwareabhängigen zum CAN Empfang
  114. *-- und eine Konsolenanwendung.
  115. * .LP
  116. *++ The hardware layer can be a direct interface routine to a CAN controller
  117. *++ or a operating system device driver.
  118. *-- Die Hardwareschicht kann ein direktes Interface zum CAN Kontroller
  119. *-- als auch ein Betriebssystem Treiber sein.
  120. * .LP
  121. *++ The console application part is used to configure
  122. *++ the application and shows the received CAN message in different formats.
  123. *++ Display formats are selectable on-line via control characters
  124. *++ typed at stdin.
  125. *-- Die Konsolenanwendung dient zur Konfiguration und zeigt die empfangenen
  126. *-- CAN Nachrichten in verschiedenen Formaten an.
  127. *-- Die Anzeigeformate sind zur Laufzeit über Kommandos
  128. *-- am Standardeingabekanal wählbar.
  129. * .LP
  130. *++ In the
  131. *++ .B "Server Mode"
  132. *++ .B horch
  133. *++ acts as a TCP/IP server waiting for a client that connects to it.
  134. *++ It can bee seen that stdin and stdout are served by the TCP/IP connection.
  135. *-- In der
  136. *-- .B Server -Betriebsart
  137. *-- wartet
  138. * .B horch
  139. *-- auf Verbindungsaufnahme von Clients über TCP/IP.
  140. *-- Die weiteren Ausführungen können so betrachtet werden,
  141. *-- als ob
  142. *-- .B stdin
  143. *-- und
  144. *-- .B stdout
  145. *-- über die TCP/IP Verbindung ersetzt werden.
  146. *++ .LP
  147. *++ The EtherCAN version of
  148. *++ .B horch
  149. *++ shows an established client connection by switching
  150. *++ .B "Status 1"
  151. *++ LED on.
  152. *-- Eine Clientverbindung zu
  153. *-- .B horch
  154. *-- wird beim EtherCAN durch einschalten der
  155. *-- .B "Status 1" -LED
  156. *-- angezeigt.
  157. * .LP
  158. *++ A special message ID, ( -c message) can be used as a debug Message
  159. *++ when developing embedded CAN applications.
  160. *++ It's contents is displayed as text string.
  161. *++ CAN devices that have no serial out for debug information can
  162. *++ use CAN via the function
  163. *++ debug_print_can(unsigned char level, char *fmt, ...);
  164. *-- Eine bestimmte Message-ID, änderbar mit
  165. *-- \fB-c \fP\fIID\fP
  166. *-- wird als Debug-Nachricht interpretiert.
  167. *-- Sie enthält einen fortlaufenden Zeichenstrom, welcher als
  168. *-- Text dargestellt wird.
  169. *-- CAN Geräte, die keinen seriellen Ausgabekanal haben,
  170. *-- könne über CAN mit der Funktion
  171. *-- debug_print_can(unsigned char level, char *fmt, ...);
  172. *-- formatierte Texte ausgeben.
  173. *
  174. *++ OPTIONS
  175. *-- OPTIONEN
  176. *
  177. * .TP
  178. * -a
  179. *-- Wenn aggegeben, dann wird der mit -b \baud\" übergebeen Wert
  180. *-- Als Inhalt der zwei Byte-Register BTR0 und BTR1 verwendet.
  181. *-- Das niederwertige Byte entspricht BTR0.
  182. *++ If specified, the \"baud\" value given with -b is used to set directly
  183. *++ the bit-timing registers BTR0 and BTR1.
  184. *++ Low byte is used for BTR0.
  185. * .CS
  186. * horch -ab 0x13c
  187. * .CE
  188. *-- Geht mit CPC-Treiber, auch EtherCAN, und can4linux.
  189. *++ Implemented for CPC-Driver, EtherCAN, and can4linux.
  190. * .TP
  191. * -b baud
  192. *-- verwendete Bit-Rate in KBaud.
  193. *++ used baud rate in Kbaud.
  194. *-- .br
  195. *-- Fehlt diese Angabe, wird der Treiber
  196. *-- mit dem Wert aus
  197. *-- .I /proc/sys/Can/Baud
  198. *-- geöffnet (LINUX can4linux).
  199. *++ Without this option
  200. *++ the driver is opened with the value from the file
  201. *++ .I /proc/sys/Can/Baud
  202. *++ (LINUX can4linux)
  203. * .IP -d
  204. *-- Debugmode einschalten
  205. *++ Switch debug mode on
  206. * .br
  207. *-- Es erfolgen Ausschriften auf
  208. *-- .B stderr ,
  209. *-- welche In\%for\%ma\%tionen zum Programmablauf
  210. *-- und zu internen Zuständen geben.
  211. *++ Messages about internal states and program flow
  212. *++ are printed to
  213. *++ .B stderr .
  214. * .TP
  215. * -C
  216. * .TP
  217. * -c CAN-ID
  218. *-- Die als Argument zur Option -c angegebene CAN-Message-ID
  219. *-- wird besonders interpretiert, wenn die Option -C gesetzt ist.
  220. *-- Ihr Inhalt wird als ASCII-Zeichenstrom ausgewertet und angezeigt.
  221. *-- CAN Applikationen haben damit die Möglichkeit Textmeldungen,
  222. *-- z.B. Debugging-Meldungen, über CAN abzusetzen.
  223. *++ The CAN message ID given as an argument to the -c option
  224. *++ gets a special interpretation if the option -C is set.
  225. *++ It's content is interpretet and displayed as an ASCII character stream.
  226. *++ CAN applications gets the opportunity to send text messages,
  227. *++ e.g. debugging messages via CAN.
  228. * .TP
  229. *-- -f <Filter Spezifikation>
  230. *++ -f <filter specification>
  231. *-- Filter für Receive Messages
  232. *++ Use a filter for all received messages
  233. * .sp
  234. *-- Ein Filter für Empfangsnachrichten wird installiert.
  235. *-- Es können variable Bereiche angegeben werden,
  236. *-- welche das Filter beim Empfang passieren.
  237. *++ This option/command installs a filter for receive messages.
  238. *++ Only messages passing the filter are displayed.
  239. *++ It is possible to specify mor then one filter area.
  240. * .sp
  241. * .CS
  242. * f 10,20,100-200,0x3e8-0x640
  243. * .CE
  244. *--Zwischen den Zahlen und Kommas dürfen keine Leerzeichen stehen.
  245. *++Spaces are not allowed between numbers and comma.
  246. *-- Default ist:
  247. *++ The default installed filter description is:
  248. * .sp
  249. * .CS
  250. * f 0-536870911
  251. * .CE
  252. *-- für alle Nachrichten (29 bit id).
  253. *++ for receiving all messages (29 bit id).
  254. .\" max 50 Bereiche definierbar, siehe filter.h MAX_RANGE
  255. * .TP
  256. * -l filename
  257. *-- Die formatierten Ausgaben können in einer Log-Datei
  258. *-- lokal gespeichert werden.
  259. *-- Der Standard Dateiname ist
  260. *-- .B logfile .
  261. *-- Mit dieser Option kann er geändert werden.
  262. *-- Die Aktivierung der Aufzeichnung erfolgt mit einem interaktiven Kommando
  263. *-- (siehe dort).
  264. *-- .br
  265. *-- Logfiles werden nicht im Server Mode angelegt.
  266. *++ The formatted display output can be saved in a local file.
  267. *++ It's default name is
  268. *++ .B logfile .
  269. *++ With this option it is possible to set a new log-file name.
  270. *++ Logging is activated sending a interactive command (see there) to
  271. *++ .B horch .
  272. *++ .br
  273. *++ Logfiles are not created in Server mode.
  274. * .TP
  275. * -p port
  276. *-- Das Internetprotokoll benutzt
  277. *-- .B Portnummer n
  278. *-- um einen bestimmten Dienst auf einem Server zu erreichen.
  279. *-- Für
  280. *-- .B horch
  281. *-- ist das die Portnummer 7235.
  282. *-- Sie kann mit dieser Option beim Start festgelegt werden.
  283. *++ The internet protocol uses the
  284. *++ .B "port number"
  285. *++ to address a specific service on an server host.
  286. *++ This is port number 7235 for
  287. *++ .B horch .
  288. *++ The port number can be set at at start time with this option.
  289. * .TP
  290. * -s time
  291. *-- Ausgabe der CAN Contoller Statusinformationen aller <time> ms.
  292. *++ Display CAN controller status information every <time> ms.
  293. * .TP
  294. * -t
  295. *-- Standardmäßig ist die Ausgabe des Zeitstempels beim Start deaktiviert
  296. *-- und kann interaktiv freigegeben werden.
  297. *-- Die Angabe dieser Option gibt die Ausgabe von Beginn an frei.
  298. *++ By default displaying of the time stamp is disabled at start up.
  299. *++ It can be enabled interactively.
  300. *++ With this option given, it is enabled at start up.
  301. *.\" .TP
  302. *.\" -C
  303. *--.\" Belege Console.
  304. *--.\" .br
  305. *--.\" Beim Start auf dem EtherCAN Modul bekommt
  306. *--.\" .B horch
  307. *--.\" die Konsole für Ein-Ausgaben zugeteil.
  308. *++.\" occupy console focus
  309. *++.\" .br
  310. *++.\" When starting
  311. *++.\" .B horch
  312. *++.\" on the EtherCAN
  313. *++.\" the console in/output is occupied by
  314. *++.\" .B horch .
  315. * .TP
  316. * -D dev
  317. *-- Auswahl des verwendeten CAN Kanals (LINUX und Windows Treiber).
  318. *-- .B dev
  319. *-- ist der verwendete Devicename und wird als /dev/<\fBdev\fR>
  320. *-- verwendet.
  321. *-- Voraussetzung ist ein installierter LINUX CAN-Devicetreiber.
  322. *++ Select the CAN channel to be used (LINUX).
  323. *++ .B dev
  324. *++ is the device name and is used as /dev/<\fBdev\fR> .
  325. *++ Precondition is a installed LINUX CAN device driver.
  326. * .TP
  327. * -S
  328. *-- Betrieb von
  329. *-- .B horch
  330. *-- im TCP/IP Server-Mode.
  331. *++ Using
  332. *++ .B horch
  333. *++ in the TCP/IP server mode.
  334. * .br
  335. *-- Der Server kann am lokalen Rechner als
  336. *-- .I localhost
  337. *-- oder innerhalb eines TCP/IP Netzwerkes mit der Portnummer 7235
  338. *-- erreicht werden.
  339. *++ This server is reachable within the local host as
  340. *++ .I localhost ,
  341. *++ or within a TCP/IP network with the name of the
  342. *++ hosted computer and the port number 7235.
  343. *-- Alle Kommandos stehen über Socket Streams zur Verfügung.
  344. *++ All commands to
  345. *++ .B horch
  346. *++ can be given over socket streams.
  347. *-- .br
  348. *-- Für Kommandobetrieb
  349. *-- kann der Server auch über
  350. *-- .B Telnet
  351. *++ For the command mode
  352. *++ the server can also be reached
  353. *++ with the common
  354. *++ .B telnet
  355. *++ application.
  356. * .sp
  357. * .CS
  358. * telnet host 7235
  359. * .CE
  360. *-- erreicht werden.
  361. * .br
  362. *-- Telnet sollte im "character" Mode betrieben werden.
  363. *-- Dadurch werden Kommandos sofort wirksam.
  364. *++ Telnet should be used with "charcter mode".
  365. *++ In this mode commands are getting immediately effective.
  366. * .CS
  367. * telnet> mode character
  368. * .CE
  369. * .TP
  370. * -T
  371. *-- Benutze Betriebssytem Zeit als Zeitstempel.
  372. *-- .br
  373. *-- Standardmäßig benutzt
  374. *-- .B horch
  375. *-- den Zeitstempel vom CAN Treiber, welcher den Empfangszeitpunkt
  376. *-- wiederspiegelt.
  377. *-- Kann der Treiber keinen Zeitstempel liefern,
  378. *-- kann statt dessen die Betriebssystemzeit
  379. *-- zum Zeitpunkt der Anzeigeformatierung ausgegeben werden.
  380. *++ use operating system time as time stamp.
  381. *++ .br
  382. *++ By default
  383. *++ .B horch
  384. *++ uses the time stamp provided by the driver at receive time.
  385. *++ If the driver does not support time stamps,
  386. *++ the opearting system time can be used.
  387. *++ Usualy this time is not the receive time, rather the display time.
  388. *
  389. * .TP
  390. * -V
  391. *-- gibt Versionsnummer auf
  392. *++ prints the version number to
  393. * .B stdout
  394. *-- aus.
  395. *
  396. *-- DISPLAY FORMAT
  397. *++ DISPLAY FORMAT
  398. *-- Empfangene CAN Messages werden im Textformat angezeigt.
  399. *-- Das allgemeine Format ist:
  400. *++ Received CAN Messages are displayed as ASCII text strings.
  401. *++ The basic format description is:
  402. * .CS
  403. [timestamp] <id-dec>/0x<id-hex> : <type> : 0{<data>}8
  404. type: <frametype> + <datatype>
  405. datatype: D|R
  406. frametype x|s
  407. example:
  408. 991330039.943806 12/0x00c : sD : 80 12 34 0d
  409. 991330039.944806 12/0x00c : xD : 80 12 34 0d
  410. 991330039.945806 4660/0x1234 : xR : (length=0)
  411. 991330039.946806 4660/0x1234 : xD : 01 02 03 04 05 06
  412. 991330039.947806 4660/0x1234 : xR : (length=4)
  413. * .CE
  414. *-- Die Message ID wird immer Dezimal und Hexadezimal dargestellt.
  415. *-- Der führende Zeitstemple ist optional und wird durch ein
  416. *-- interaktives Kommando aktiviert.
  417. *-- Die Darstellung der Daten kann durch interaktive Kommandos
  418. *-- zwischen Hexadezimal, Dezimal und ASCII-Zeichen
  419. *-- ausgewählt werden.
  420. *++ The message ID is always displayed in decimal and hexa-decimal.
  421. *++ The leading time stamp value is optional and can be activated
  422. *++ by an interactive command.
  423. *++ The format of the displayed data bytes
  424. *++ can be selected by interactive commands
  425. *++ from decimal, hexa-decimal or ascii characters.
  426. *
  427. *-- INTERAKTIVE KOMMANDOS
  428. *++ INTERACTIVE COMMANDS
  429. .B horch
  430. *-- kann zur Laufzeit auf seinem Eingabekanal
  431. *-- (stdin Konsole oder von TCP/IP)
  432. *-- Kommandos entgegennehmen,
  433. *-- welche einige seiner Parameter ändern können.
  434. *-- Die meisten Kommandos bestehen aus einem Kommandobuchstaben
  435. *-- und beeinflussen die Ausgabeformatierung von CAN Nachrichten.
  436. *-- Im Fall das stdin von der Konsole kommt,
  437. *-- benutzt
  438. *-- .B horch
  439. *-- das Kommando
  440. *-- .I stty(1)
  441. *-- um die Konsole in die Betriebsart
  442. *-- .B "cbreak, noecho"
  443. *-- zu schalten.
  444. *++ can be controlled through commands from it's stdin channel
  445. *++ (console or TCP/IP).
  446. *++ Most commans consist of one letter
  447. *++ and are used to change formatting of CAN messages.
  448. *++ In the case stdin comes from the console
  449. *++ .B horch
  450. *++ uses the command
  451. *++ .I stty (1)
  452. *++ to switch the console int the
  453. *++ .B "raw, noecho"
  454. *++ mode.
  455. .TP
  456. ?
  457. *-- On-line Hilfe, Kommandoübersicht auf stdout
  458. *++ On-line help, command overview to stdout
  459. .TP
  460. a
  461. *-- Formatierung der Datenbytes als ASCII Zeichen
  462. *++ Formatting of data bytes as ASCII characters
  463. .TP
  464. b
  465. *-- Setzen der Bit Rate on-line
  466. *++ change bit rate on-line
  467. * .CS
  468. * b 125
  469. * .CE
  470. *-- Jeder gültige CANopen Wert ist zulässig
  471. *++ Every valid CANopen bit rate value is allowed
  472. .TP
  473. c
  474. *-- Ausgabe einer Trennlinie auf stdout
  475. *++ print cut-mark to stdout
  476. .TP
  477. d
  478. *-- Formatierung der Datenbytes als Dezimalzahlen
  479. *++ Formatting of data bytes as decimal numbers
  480. .TP
  481. f
  482. *-- Installiert ein Filter für Empfangs Nachrichten
  483. *-- Die Filter-Format Spezifikation ist unter der Option -f beschrieben.
  484. *++ Installes a filter for receive messages.
  485. *++ For the format of filter specification see command option -f.
  486. .TP
  487. h
  488. *-- Formatierung der Datenbytes als Hexadezimalzahlen
  489. *++ Formattting of data bytes as hexa-decimal numbers
  490. .TP
  491. i
  492. *-- Auf Linux Systemen kann ein Interpreter aufgerufen werden,
  493. *-- welcher den aktuellen Inhalt des
  494. *-- .B logfile
  495. *-- interpretiert.
  496. *++ On LINUX Systems a Interpreter progarmm can be startet
  497. *++ which interprets and displays the content of the actual
  498. *++ .B logfile .
  499. .TP
  500. l
  501. *-- Wechselt den aktuellen Logging Zustand für lokales Aufzeichen.
  502. *++ toggles state of lokal file logging.
  503. *-- Logfiles werden nicht im Server Mode angelegt.
  504. *++ Logfiles are not created in Server mode.
  505. .TP
  506. m acc_code acc_mask
  507. *-- Setzt Akzeptanz und Mask Register des CAN SJA1000 Controllers.
  508. *-- Mit diesem Kommando er\%reicht man eine Nachrichtenfilterung durch den CAN
  509. *-- Controller.
  510. *++ Set the content of acceptance and mask register of the SJA1000 CAN
  511. *++ controller chip.
  512. *++ With the help of this command a message filter based on the CAN chip
  513. *++ hardware is possible.
  514. *++ (see SJA1000 documentation)
  515. .br
  516. *--acc_code und acc_mask
  517. *++acc_code and acc_mask
  518. *-- kann ein 32 bit wert in dezimaler oder hexadezimaler Schreibweise sein.
  519. *++ can be a 32 bit value as decimal or hexadecimal number.
  520. .TP
  521. q
  522. *-- Programm beenden
  523. *++ quit program
  524. .TP
  525. R
  526. *-- Resettet den CAN Controller, z.B. nach einem Error Busoff.
  527. *++ Reset the CAN controller, e.g. after a Error Busoff.
  528. .TP
  529. r
  530. *-- Rücksetzen der
  531. *-- .B horch
  532. *-- Statistikwerte
  533. *++ reset the values of
  534. *++ .B horch
  535. *++ statistic variables.
  536. .TP
  537. s
  538. *-- Ausgaben von Statistikinformationen
  539. *++ display statistic informations
  540. .br
  541. *-- Es gibt hier kein allgemeingültiges Format.
  542. *-- Die Statusinformationen sind vom verwendeten CAN Controller im
  543. *-- Layer-2 Treiber abhängig.
  544. *-- Die erste Spalte gibt im Klartext den Namen des CAN-Controllers an,
  545. *-- es folgen, als Dezimalzahlen, die Inhalte verschiedener Register.
  546. *-- Für den am meisten verwendeten SJA1000 sieht eine Statistikzeile folgendermasssen aus:
  547. *++ For the most often used CAN controller SJA1000 a statistic line looks like this:
  548. .LS
  549. :: sja1000 <act baud rate> <status register> <error_warning limit> <rx errors> <tx errors> <error code> <buslast>
  550. .LE
  551. .TP
  552. t
  553. *-- aktivieren der Anzeige von Zeitmarken.
  554. *++ activate display of time stamps.
  555. .TP
  556. T
  557. *-- deaktivieren der Anzeige von Zeitmarken.
  558. *++ deactivate display of time stamps.
  559. .TP
  560. y
  561. *-- aktivieren des Triggers
  562. *++ start the trigger
  563. .TP
  564. Y
  565. *-- deaktivieren des Trigger
  566. *++ stop the trigger
  567. .TP
  568. x
  569. *-- Übertragen von Triggereinstellungen
  570. *++ change trigger settings
  571. * .br
  572. *-- Format: x idx mask RTR id [data]
  573. *-- idx ist ein Wert zwischen 0 und 2 und spezifiziert einen Triggerpuffer
  574. *-- Mask ist eine Bitmaske womit don't care-Bytes in der CAN_Nachricht angegeben
  575. *-- werden.
  576. *-- Ist der 3 Parameter ein r so wird auf eine RTR-Nachricht hin getriggert
  577. +-- id ist gewünschte CAN-ID
  578. *-- data sind optionale Datenbytes der Nachricht
  579. *++ Format: x idx mask RTR id [data]
  580. *++ idx is a value between 0 and 2 and specifies a trigger buffer
  581. *++ Mask specifies which bytes are don't care bytes.
  582. *++ Is the 2nd parameter a r, so the trigger waits for a RTR Message
  583. *++ id is the wanted CAN-ID
  584. *++ data are the optional data bytes of the message
  585. .TP
  586. w
  587. *-- Senden einer CAN Message.
  588. *++ send a CAN message
  589. * .br
  590. *-- Eine CAN Message kann gesendet werden.
  591. *-- Nach diesem Kommando werden alle folgenden Zeichen bis zu einem NewLine
  592. *-- als Argumente ausgewertet.
  593. *-- Das Kommando mit Großbuchstaben \fBW\fP wird zum Senden von Nachrichten
  594. *-- im extended Format (29 Bit) benutzt.
  595. *-- Folgt dem Kommandobuchstaben als erstes Argument der Buchstabe \fBr\fP
  596. *-- wird eine RTR Message versendet.
  597. *++ A CAN message is sent.
  598. *++ All of the letters following the command letter are interpreted
  599. *++ as arguments.
  600. *++ The capital command letter \fBW\fP is used to send in extended message
  601. *++ format (using 29 bits)
  602. *++ If the letter \fBr\fP is following the command letter as first argument,
  603. *++ an RTR message is sent.
  604. * .sp
  605. * .CS
  606. * w [r] id 0{data}8
  607. *
  608. * w 222 0xaa 0x55 100 ; standard message with three data bytes
  609. * w r 0x100 0 0 0 ; standard rtr message with data length code 3
  610. * W 0x100 1 2 ; extended message with two data bytes
  611. * .CE
  612. .TP
  613. H
  614. *-- Formatierung der Datenbytes als Hexadezimalzahlen
  615. *++ Formattting of data bytes as hexa-decimal numbers
  616. * .br
  617. *-- Im Gegensatz zu
  618. *-- .B h ,
  619. *-- werden die Datensätze bei eingeschaltetem
  620. *-- Aufzeichnen (logging) binär, als canmsg_t Struktur gespeichert.
  621. *-- Alle anderen Formatierungen speichern die Datensätze als ASCII
  622. *-- Zeilen.
  623. *++ Opposite to the
  624. *++ .B h
  625. *++ command letter,
  626. *++ CAN message data are stored as binary data as canmsg_t structure
  627. *++ if local file logging is enabled (-l).
  628. *++ All other formats are stored as ASCII character lines.
  629. .ig
  630. A Filter should be installed, possibly with using the hardware
  631. acceptance filter of the CAN controller.
  632. Kommandos for formatting, but at least for filtering messages
  633. must be received by the server via socket and via stdin.
  634. f1, 100-200, 555, 1200-
  635. (like the page -o option of troff)
  636. (also for the logging feature of m4d useful)
  637. ..
  638. ++ CAN ERROS
  639. -- CAN FEHLER
  640. -- Vom Treiber erkannte CAN Fehler werden im Klartext zur Konsole
  641. -- geschrieben.
  642. -- Die folgenden selbsterklärenden werden erkannt:
  643. ++ Errors recognized by the driver are displayed at the console
  644. ++ as text messages.
  645. ++ The following messages are known:
  646. .CS
  647. "ERROR: OVERRUN" CAN chip overrun
  648. "ERROR: PASSIVE"
  649. "ERROR: BUSOFF"
  650. "ERROR: Buffer OVERRUN" can4linux software buffer overrun
  651. .CE
  652. SEE ALSO
  653. can4linux(7), stty(1), telnet(1)
  654. NOROUTINES
  655. */
  656. #define MAX_TRIGGER_MESSAGES 3 /* 0,1,2 */
  657. #include <horch.h>
  658. #if defined(EMBED) && defined(CONFIG_COLDFIRE)
  659. #include "filter.h"
  660. #else
  661. #include <filter/filter.h>
  662. #endif
  663. #ifdef TARGET_IPC
  664. #include <can/can.h>
  665. #endif
  666. #ifdef TARGET_LX_WIN_BC
  667. # include <canopen.h>
  668. # include <target.h>
  669. # include <conio.h>
  670. #endif
  671. /* global program options, typical o_ but debug */
  672. int debug = FALSE;
  673. char *log_file = LOGFILE;
  674. FILE *log_fp = NULL;
  675. char *fmt = "%02x ";
  676. unsigned int testCOB = TESTCOB;
  677. int o_debugmessage = FALSE;
  678. int o_timestamp = FALSE;
  679. int save_binary = FALSE;
  680. int show_time = TRUE;
  681. int o_use_drivers_time = TRUE;
  682. int o_server = FALSE; /* TCP/IP Server */
  683. int o_udpserver = FALSE; /* UDP/IP Server */
  684. int o_focus = FALSE; /* dont switch console if IPC */
  685. long o_period = 1000000; /* bus load period in us, default 1 sec */
  686. int o_show_status = FALSE;
  687. #ifdef TARGET_IPC
  688. int o_bitrate = 125; /* default 125kBit */
  689. #elif defined(TARGET_LINUX)
  690. int o_bitrate = 0; /* use /proc/sys/Can/Baud */
  691. #else
  692. int o_bitrate = 125; /* default 125kBit */
  693. #endif
  694. int o_btr = FALSE; /* if set, use o_bitrate as BTR value */
  695. int o_portnumber = 7235;
  696. char device[40]; /* Device */
  697. #ifdef TARGET_LX_WIN_BC
  698. int board_nr = 0; /* number of device */
  699. extern int o_Device;
  700. #endif /* TARGET_LX_WIN_BC */
  701. #if defined(TARGET_LX_WIN_BC)
  702. extern char o_boardname_ptr[];
  703. #elif defined(TARGET_CPC_ECO)
  704. /* same for unix and Windows - not used for ARM */
  705. extern char o_boardname_ptr[];
  706. #endif
  707. /* other globals */
  708. #ifdef CONFIG_SK
  709. unsigned long lifecount;
  710. #endif
  711. unsigned long interrupts;
  712. unsigned long dlines;
  713. unsigned char care_mask[MAX_TRIGGER_MESSAGES];
  714. char trigger = 0;
  715. canmsg_t triggermessage[MAX_TRIGGER_MESSAGES];
  716. SOCKET server_fd; /* socket file descriptor */
  717. float f_busload = 0; /* global bus load variable */
  718. unsigned int u32_bits = 0; /* number of received bits within a period */
  719. /* functions */
  720. static char *sbuf(unsigned char *s, int n, char *fmt);
  721. static void usage(char *s);
  722. static void online_help(void);
  723. static void clean(void);
  724. static int cut_mark(void);
  725. void quit(char *line);
  726. void settrigger(char *);
  727. char compare_msg(unsigned char, canmsg_t *, canmsg_t *);
  728. int getopt(int, char * const *, const char *);
  729. void add_bits(unsigned char, unsigned char);
  730. static void alarmhandler (int signo);
  731. void termination_handler(
  732. int signum /* signal to handle */
  733. )
  734. {
  735. /* remove the file containing the process id */
  736. #ifdef LINUX_ARM
  737. if( -1 == unlink(PIDFILE)) {
  738. perror("remove pid file");
  739. }
  740. #endif
  741. clean_up();
  742. }
  743. /***************************************************************************
  744. *
  745. * main - main entrypoint
  746. *
  747. */
  748. int main(int argc, char * argv[])
  749. {
  750. int id;
  751. int c,which;
  752. char *options; /* getopt options string */
  753. extern char *optarg;
  754. extern int optind, opterr, optopt;
  755. char *pname;
  756. #if defined(TARGET_LINUX)
  757. # if defined(LINUX_ARM) || defined(CPC_LINUX)
  758. # else /* defined(LINUX_ARM) || defined(CPC_LINUX) */
  759. itimerval value1, ovalue;
  760. CanStatusPar_t status;
  761. int can_fd;
  762. # endif /* defined(LINUX_ARM) || defined(CPC_LINUX) */
  763. #endif /* TARGET_LINUX */
  764. pname = *argv;
  765. sprintf(device, "%s", STDDEV);
  766. /* common options for all versions */
  767. options = "CSTVab:c:dhf:l:p:s:tu"
  768. #if defined(TARGET_LINUX)
  769. "D:" /* Driver selection */
  770. #endif
  771. #if defined(TARGET_LX_WIN_BC)
  772. "D:U:B:" /* Driver/DriverPort selection */
  773. #endif
  774. #if defined(TARGET_CPC_ECO) && defined(__WIN32__)
  775. "D:" /* Driver/DriverPort selection */
  776. #endif
  777. ;
  778. while ((c = getopt(argc, argv, options)) != EOF) {
  779. switch (c) {
  780. case 'C':
  781. o_debugmessage = TRUE;
  782. break;
  783. #if defined(TARGET_LINUX)
  784. case 'D':
  785. # ifdef TARGET_CPC_ECO
  786. /* Linux version of CPC driver */
  787. sprintf(o_boardname_ptr, "/dev/%s", optarg);
  788. # else /* TARGET_CPC_ECO */
  789. /* can4linux */
  790. sprintf(device, "/dev/%s", optarg);
  791. # endif /* TARGET_CPC_ECO */
  792. break;
  793. #endif
  794. #if defined(TARGET_LX_WIN_BC)
  795. case 'D':
  796. o_Device = atoi(optarg); /* Device number */
  797. break;
  798. case 'B':
  799. o_boardname_ptr = optarg; /* Boardname */
  800. break;
  801. case 'U':
  802. board_nr = atoi(optarg); /* Board number */
  803. break;
  804. #endif
  805. #if defined(TARGET_CPC_ECO) && defined(__WIN32__)
  806. case 'D':
  807. /* Win32 version of CPC driver */
  808. /* Device name found at cpcconf.ini */
  809. /*o_boardname_ptr = optarg;*/
  810. strcpy(o_boardname_ptr, optarg);
  811. break;
  812. #endif
  813. case 'S':
  814. o_server = TRUE;
  815. break;
  816. case 'T':
  817. o_use_drivers_time = FALSE;
  818. break;
  819. case 'u':
  820. o_udpserver = TRUE;
  821. break;
  822. case 'a':
  823. o_btr |= 1;
  824. break;
  825. case 'b':
  826. o_bitrate = (int)strtol(optarg, NULL, 0);
  827. o_btr |= 2;
  828. break;
  829. case 'f':
  830. read_fp_string(optarg);
  831. break;
  832. case 'l':
  833. log_file = optarg;
  834. break;
  835. case 'd':
  836. debug = TRUE;
  837. break;
  838. case 'c':
  839. testCOB = (int)strtol(optarg, NULL, 0);
  840. break;
  841. #ifndef CONFIG_SK
  842. case 'p':
  843. o_portnumber = (int)strtol(optarg, NULL, 0);
  844. break;
  845. case 's':
  846. o_period = 1000 * atoi(optarg);
  847. o_show_status = TRUE;
  848. break;
  849. #endif
  850. case 't':
  851. o_timestamp = TRUE;
  852. break;
  853. case 'V':
  854. printf("\"horch\" "
  855. #ifdef CONFIG_SK
  856. " SK"
  857. #endif
  858. " Revision: %s, %s, %s\n",
  859. horch_revision, __DATE__, __TIME__);
  860. exit(0);
  861. break;
  862. case 'h':
  863. default: usage(pname); exit(0);
  864. }
  865. }
  866. /* if -a, also -b should be used */
  867. if(o_btr & 1 && o_btr != 3) {
  868. fprintf(stderr, "use always -b baud when specifying -a\n\n");
  869. usage(pname); exit(0);
  870. }
  871. #if defined(TARGET_LINUX)
  872. if(debug) {
  873. printf("using CAN device %s\n", device);
  874. if(o_btr & 1) {
  875. printf(" use BTR0 = 0x%02x, BTR1 = 0x%02x\n",
  876. o_bitrate & 0xff, o_bitrate >> 8);
  877. } else {
  878. printf(" use bitrate %d\n", o_bitrate);
  879. }
  880. }
  881. /* Installing Signal handler */
  882. if (signal (SIGINT, termination_handler) == SIG_IGN)
  883. signal (SIGINT, SIG_IGN);
  884. if (signal (SIGHUP, termination_handler) == SIG_IGN)
  885. signal (SIGHUP, SIG_IGN);
  886. if (signal (SIGTERM, termination_handler) == SIG_IGN)
  887. signal (SIGTERM, SIG_IGN);
  888. /* SIGALRM is used to call cyclic bus load calculation */
  889. if (signal(SIGALRM, alarmhandler) == SIG_ERR){
  890. fprintf(stderr,"can't catch SIGALARM");
  891. }
  892. # if defined(LINUX_ARM) || defined(CPC_LINUX)
  893. /* ARM-Linux version of CPC driver */
  894. # else /* defined(LINUX_ARM) || defined(CPC_LINUX) */
  895. /* reading baud rate out of /proc/sys/can/Baud, if o_bitrate == 0; */
  896. if (o_bitrate == 0) {
  897. can_fd = open (device,O_RDWR);
  898. ioctl(can_fd, STATUS, &status);
  899. o_bitrate = status.baud;
  900. close(can_fd);
  901. }
  902. which = ITIMER_REAL;
  903. value1.it_interval.tv_sec = 0;
  904. value1.it_interval.tv_usec = o_period;
  905. value1.it_value.tv_sec = 0;
  906. value1.it_value.tv_usec = o_period;
  907. which = setitimer(which, (struct itimerval *)&value1,
  908. (struct itimerval *)&ovalue);
  909. # endif /* defined(LINUX_ARM) || defined(CPC_LINUX) */
  910. #endif /* defined(TARGET_LINUX) */
  911. #ifdef CONFIG_SK
  912. /* calculate time to life */
  913. /* min */
  914. lifecount = (60 * 60 * 1000000UL) / o_period;
  915. #endif
  916. /* now we are running, put our process id into /var/run */
  917. #ifdef LINUX_ARM
  918. {
  919. FILE *fp;
  920. int pid = getpid();
  921. fp = fopen(PIDFILE, "w");
  922. if( fp == NULL) {
  923. perror("open pid file");
  924. } else {
  925. fprintf(fp, "%d", pid);
  926. fclose(fp);
  927. }
  928. }
  929. #endif
  930. /* set trigger messages to 0x000 0x00 0x00 0x00 0x00 ... */
  931. settrigger(" 0 0xff 0x000 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00");
  932. settrigger(" 1 0xff 0x000 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00");
  933. settrigger(" 2 0xff 0x000 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00");
  934. /* configure terminal mode */
  935. set_up();
  936. if(o_server) {
  937. if(o_udpserver) {
  938. udp_event_loop();
  939. } else {
  940. server_event_loop();
  941. }
  942. } else {
  943. event_loop();
  944. }
  945. /* close files and devices, restore terminal settings ,... */
  946. termination_handler(0);
  947. return 0;
  948. }
  949. /***************************************************************************
  950. *
  951. * sbuf - show an byte array with format spec
  952. *
  953. * formats n databytes as specified in fmt.
  954. *
  955. * RETURNS
  956. * .TP
  957. * pointer to string
  958. */
  959. static char *sbuf(
  960. unsigned char *s, /* pointer to byte array */
  961. int n, /* nuber of conversions */
  962. char *fmt /* printf() format string */
  963. )
  964. {
  965. int i;
  966. static char string[128];
  967. int ascii = 0; /* flag for ascii char display */
  968. char *ptr;
  969. string[0] = 0;
  970. ptr = &string[0];
  971. if( *(fmt+1) == 'c') ascii = 1;
  972. for(i = 0; i < n; i++) {
  973. if(ascii) {
  974. ptr += sprintf(ptr, fmt, (*s < ' ' || *s > 0x7e) ? '.' : *s);
  975. s++;
  976. } else {
  977. ptr += sprintf(ptr, fmt, *s++);
  978. }
  979. }
  980. *(ptr++) = '\n';
  981. *ptr = '\0';
  982. return(&string[0]);
  983. }
  984. char send_line[2056]; /* formatted message */
  985. char debug_line[2056]; /* formatted CAN debug message */
  986. int send_line_cnt = 0;
  987. static char *l_ptr = &send_line[0]; /* pointer stays for multi line */
  988. void reset_send_line(void )
  989. {
  990. send_line[0] = 0;
  991. send_line_cnt = 0;
  992. l_ptr = &send_line[0];
  993. }
  994. /***************************************************************************
  995. *
  996. * add_time - display the timestamp
  997. *
  998. * RETURNS
  999. * The buffer pointer is going increment.
  1000. */
  1001. void add_time(
  1002. char **pl_ptr, /* pointer to buffer pointer */
  1003. canmsg_t *m /* pointer to message structur */
  1004. )
  1005. {
  1006. if ((show_time == TRUE) && (o_timestamp))
  1007. {
  1008. /* first add the timestamp to the line */
  1009. if(o_use_drivers_time) {
  1010. #ifdef TARGET_IPC
  1011. *pl_ptr += sprintf(*pl_ptr, "%12lu ", 0UL);
  1012. #else
  1013. *pl_ptr += sprintf(*pl_ptr, "%12lu.%06lu ",
  1014. m->timestamp.tv_sec,
  1015. m->timestamp.tv_usec);
  1016. #endif
  1017. } else {
  1018. *pl_ptr += show_system_time(*pl_ptr);
  1019. }
  1020. } /* show_time */
  1021. }
  1022. /***************************************************************************
  1023. *
  1024. * show_message - display the formatted CAN message
  1025. *
  1026. * formats the CAN message according to many flags
  1027. *
  1028. * RETURNS
  1029. * .TP
  1030. * nothing
  1031. */
  1032. int show_message(
  1033. canmsg_t *m /* pointer to message struct */
  1034. )
  1035. {
  1036. int j;
  1037. char *t_ptr; /* temporärer Zeiger for normal can formatting*/
  1038. static char *d_ptr = &debug_line[0]; /* temporärer Zeiger for debug message*/
  1039. char **pl_ptr; /* show to the l_ptr ord d_ptr */
  1040. char trig_c,trig_f; /* variables for the trigger */
  1041. *l_ptr = '\0';
  1042. /* detect special driver flags */
  1043. if( m->flags & MSG_ERR_MASK ) {
  1044. if( m->flags & MSG_OVR ) {
  1045. add_time(&l_ptr, m);
  1046. strcpy(l_ptr, "ERROR: OVERRUN\n");
  1047. while(*l_ptr++ != '\n');
  1048. /* Call skip if message at all is not useful.
  1049. * but continue else. Than we have two lines:
  1050. * 1. overrun
  1051. * 2. message
  1052. */
  1053. /* goto skip; */
  1054. }
  1055. if( m->flags & MSG_PASSIVE ) {
  1056. add_time(&l_ptr, m);
  1057. strcpy(l_ptr, "ERROR: PASSIVE\n");
  1058. while(*l_ptr++ != '\n');
  1059. }
  1060. if( m->flags & MSG_BUSOFF ) {
  1061. add_time(&l_ptr, m);
  1062. strcpy(l_ptr, "ERROR: BUSOFF\n");
  1063. while(*l_ptr++ != '\n');
  1064. }
  1065. if( m->flags & MSG_BOVR ) {
  1066. add_time(&l_ptr, m);
  1067. strcpy(l_ptr, "ERROR: Buffer OVERRUN\n");
  1068. while(*l_ptr++ != '\n');
  1069. }
  1070. } /* CAN Errors */
  1071. /* count display lines for statistical and debugging reasons */
  1072. dlines++;
  1073. /* check for debug message id */
  1074. /* Bei der Debug Message wird Text Angezeigt, und nur bei
  1075. * der ersten eine Timestamp, d.h. wenn kein newline in der message
  1076. * folgt offensichtlich text,
  1077. * und die Timestampanzeige wird unterdrückt.
  1078. * Besser Text in einem sep Puffer sammeln,
  1079. * und bei der letzten Message, mit Newline, ausgeben.
  1080. */
  1081. if ((o_debugmessage == TRUE) && (testCOB == m->id)) {
  1082. if ((testCOB == m->id) && (d_ptr != &debug_line[0])) {
  1083. } else {
  1084. add_time( &d_ptr, m);
  1085. }
  1086. memcpy( d_ptr, m->data, m->length);
  1087. d_ptr += m->length;
  1088. *d_ptr = '\0';
  1089. /* test for an Carriage return */
  1090. for (j = 0; j < m->length; j++) {
  1091. if (m->data[j] == '\n') {
  1092. display_line(debug_line);
  1093. d_ptr = &debug_line[0]; /* reset line */
  1094. break;
  1095. }
  1096. }
  1097. return 0;
  1098. } /* Debug Messages */
  1099. if (m->id != (unsigned long)-1) {
  1100. add_time(&l_ptr, m);
  1101. /* No debug message, display message ID */
  1102. show_time = TRUE; /* ?????????? */
  1103. l_ptr += sprintf(l_ptr, "%4ld/0x%03lx : ", m->id, m->id);
  1104. if( m->flags & MSG_EXT ) {
  1105. /* if message is in extended format, flag it */
  1106. l_ptr += sprintf(l_ptr, "x");
  1107. } else {
  1108. /* if message is in standard format, flag it */
  1109. l_ptr += sprintf(l_ptr, "s");
  1110. }
  1111. if( m->flags & MSG_RTR ) {
  1112. l_ptr += sprintf(l_ptr, "R : ");
  1113. l_ptr += sprintf(l_ptr, "(length=%d)\n",(int)m->length); /* format data bytes */
  1114. } else {
  1115. l_ptr += sprintf(l_ptr, "D : ");
  1116. t_ptr = sbuf(m->data , m->length, fmt); /* format data bytes */
  1117. while(*t_ptr != '\0') {
  1118. *l_ptr++ = *t_ptr++;
  1119. }
  1120. *l_ptr = '\0';
  1121. }
  1122. } /* CAN Message */
  1123. skip:
  1124. /* Bus load messurement routines */
  1125. add_bits(m->flags,m->length);
  1126. /* ERROR Messages will pass the Trigger */
  1127. if ( (m->flags & MSG_ERR_MASK) == 0) {
  1128. /* If the trigger is not used, every message is displayed */
  1129. if (trigger == 1) {
  1130. /* here we check, if the received line matches our triggermessages */
  1131. trig_f = 0; /* Trigger Flag */
  1132. for (trig_c = 0; (trig_c < MAX_TRIGGER_MESSAGES) && (trig_f == 0);\
  1133. trig_c ++)
  1134. {
  1135. trig_f |= compare_msg(care_mask[trig_c], m, \
  1136. &triggermessage[trig_c]);
  1137. }
  1138. if (trig_f != 0 ) {
  1139. trigger = 0;
  1140. } else {
  1141. reset_send_line();
  1142. return 0;
  1143. }
  1144. } /* end trigger */
  1145. }
  1146. #if 0
  1147. if(!o_server && display_line(send_line) == -1) {
  1148. l_ptr = &send_line[0]; /* reset format pointer */
  1149. return -1;
  1150. }
  1151. #else /* 0 */
  1152. if(!o_server) {
  1153. /* in local mode only save to logfile */
  1154. /* in local mode, sending to stdout, print each line */
  1155. display_line(send_line);
  1156. if(log_fp) {
  1157. /* log data to file */
  1158. if(save_binary) {
  1159. /* log data to file */
  1160. /* src, length count, fp */
  1161. fwrite((void *)m, sizeof(canmsg_t), 1, log_fp);
  1162. } else {
  1163. fprintf(log_fp, "%s", send_line);
  1164. }
  1165. }
  1166. reset_send_line();
  1167. }
  1168. #endif /* 0 */
  1169. if(o_server) {
  1170. /* adjust l_ptr to end of formatted string */
  1171. /* next message is written at the end
  1172. */
  1173. /* while(*l_ptr++ != '\n'); */
  1174. }
  1175. send_line_cnt = l_ptr - &send_line[0];
  1176. return 0;
  1177. }
  1178. /*
  1179. Interpretation der Eingaben
  1180. es werden Kommandobuchstaben ausgewertet.
  1181. Die meisten Funktionen ändern das Ausgabeformat der CAN Nachricht.
  1182. Kommando 'c'
  1183. gibt eine Begrenzungslinie aus.
  1184. Bei der Ausgabe zum Socket stream kann ein Schreibfehler vorkommen.
  1185. RETURNS
  1186. .TP
  1187. OK
  1188. .TP
  1189. -1
  1190. Error while sending to socket
  1191. */
  1192. int change_format(char c)
  1193. {
  1194. static unsigned char line[MAX_CLINE];/* command line buffer */
  1195. static char command = 0; /* collect data for a complete line */
  1196. static int cnt = 0; /* count input chars */
  1197. if(command != '\0') {
  1198. /* =================================================================*/
  1199. /* add character to command line */
  1200. if(c != '\n' && c != '\r') {
  1201. if(cnt == MAX_CLINE) {
  1202. command = '\0';
  1203. cnt = 0;
  1204. return 0;
  1205. }
  1206. line[cnt++] = c;
  1207. } else {
  1208. /*
  1209. * end of line, give it to a function.
  1210. * Line does not start with the command letter
  1211. * and does not end with Newline
  1212. */
  1213. line[cnt] = '\0';
  1214. /* first select function which has requested a line */
  1215. switch(command) {
  1216. case 'w': /* write */
  1217. #ifdef TARGET_IPC
  1218. write_message(&line[0]);
  1219. #else
  1220. write_message(0, &line[0]);
  1221. #endif
  1222. break;
  1223. #ifdef TARGET_IPC
  1224. #else
  1225. case 'W': /* write */
  1226. write_message(1, &line[0]);
  1227. break;
  1228. #endif
  1229. case 'f': /* filter */
  1230. read_fp_string(&line[0]);
  1231. break;
  1232. #ifdef TARGET_IPC
  1233. #else
  1234. case 'b': /* bit rate */
  1235. set_bitrate(&line[0]);
  1236. break;
  1237. case 'm': /* acceptance mask */
  1238. set_acceptance(&line[0]);
  1239. break;
  1240. #endif
  1241. case 'x': /*set Trigger parameter */
  1242. settrigger(&line[0]);
  1243. break;
  1244. case 'Q': /*set Trigger parameter */
  1245. quit(&line[0]);
  1246. break;
  1247. default: break;
  1248. }
  1249. command = '\0'; /* reset command -- finished */
  1250. cnt = 0; /* and char counter */
  1251. }
  1252. } else {
  1253. /* =================================================================*/
  1254. /* interpret character as command */
  1255. switch(c) {
  1256. /* define letters for commands which are collecting a line */
  1257. case 'f': /* filter command, collects line */
  1258. case 'w': /* write command, collects line */
  1259. case 'W':
  1260. case 'x': /* collects line for trigger settings */
  1261. case 'Q': /* collects line for Quit command */
  1262. #if defined(TARGET_LINUX) || defined(__WIN32__)
  1263. case 'm':
  1264. /* set acceptance and mask register in case of SJA1000 */
  1265. case 'b':
  1266. /* set bit rate */
  1267. #endif
  1268. command = c;
  1269. break;
  1270. /*--------------------------------------------------------------*/
  1271. case 'a': /* ASCII format */
  1272. fmt = "%c";
  1273. break;
  1274. case 'c':
  1275. /* put 'cut'-mark at display */
  1276. return(cut_mark());
  1277. case 'd': /* decimal format */
  1278. fmt = "%03d ";
  1279. break;
  1280. case 'h': /* hex format */
  1281. fmt = "%02x ";
  1282. save_binary = FALSE;
  1283. break;
  1284. #ifdef TARGET_LINUX
  1285. case 'i':
  1286. system("konvert -L -x std.int -n std.nam logfile | less");
  1287. break;
  1288. #endif
  1289. case 'l':
  1290. if(log_fp) {
  1291. /* log file already opened */
  1292. fprintf(stderr, "close log file: %s\n",
  1293. log_file);
  1294. fclose(log_fp);
  1295. log_fp = NULL;
  1296. } else {
  1297. /* must open log file
  1298. * doing this with deleting the old file
  1299. */
  1300. if( (log_fp = fopen(log_file, "w")) == NULL ) {
  1301. fprintf(stderr, "open log file error %d;",
  1302. errno);
  1303. perror("");
  1304. }
  1305. fprintf(stderr, "opened log file: %s (%s)\n",
  1306. log_file,
  1307. (save_binary ? "binary" : "Ascii"));
  1308. }
  1309. break;
  1310. case 'R':
  1311. /* Reset the CAN contorller */
  1312. sprintf(line, "%d", o_bitrate);
  1313. set_bitrate(&line[0]);
  1314. break;
  1315. case 'q':
  1316. if(o_server) {
  1317. /* only for test purposes a client can finish the server */
  1318. /* clean_up(); */
  1319. return -1;
  1320. } else {
  1321. clean_up();
  1322. }
  1323. break;
  1324. case 'r': /* reset statistik */
  1325. interrupts = 0;
  1326. dlines = 0; /* number of displayed message lines */
  1327. break;
  1328. case 's': /* show statistik */
  1329. {
  1330. #if defined(TARGET_LINUX)
  1331. char line[400];
  1332. getStat(line); /* fills line !! */
  1333. sprintf(line,"%s %.1f\n",line,f_busload);
  1334. #else
  1335. char line[40];
  1336. sprintf(line, ":: %ld Interrupts, %ld lines\n",
  1337. interrupts, dlines);
  1338. #endif
  1339. send_line_cnt = strlen(line);
  1340. display_line(line);
  1341. send_line_cnt = 0;
  1342. }
  1343. break;
  1344. case 't': /* activate time stamp display */
  1345. o_timestamp = TRUE;
  1346. break;
  1347. case 'T': /* de-activate time stamp display */
  1348. o_timestamp = FALSE;
  1349. break;
  1350. case 'H': /* Hex format and binary log */
  1351. fmt = "%02x ";
  1352. save_binary = TRUE;
  1353. break;
  1354. case '?':
  1355. online_help();
  1356. break;
  1357. case 'y': /* start trigger */
  1358. trigger = 1;
  1359. break;
  1360. case 'Y': /* stop trigger */
  1361. trigger = 0;
  1362. break;
  1363. #ifdef TARGET_IPC
  1364. /* test for Queue overrun */
  1365. case ('S' - 0x40):
  1366. printf("---- Stopped\n");
  1367. while(1) {
  1368. Sleep(2);
  1369. if(kbhit()) {
  1370. if(getch() == ('Q' - 0x40)) break;
  1371. }
  1372. }
  1373. printf("---- Continue\n");
  1374. break;
  1375. #endif
  1376. default:
  1377. break;
  1378. }
  1379. }
  1380. return 0;
  1381. }
  1382. /***********************************************************************
  1383. *
  1384. * usage - print usage of the command to stderr
  1385. *
  1386. * RETURN: N/A
  1387. *
  1388. */
  1389. static void usage(
  1390. char *s /* program name */
  1391. )
  1392. {
  1393. static char *usage_text = "\
  1394. "
  1395. #ifdef TARGET_LINUX
  1396. "\
  1397. -D - name use CAN device name /dev/<name>, default is %s\n\
  1398. "
  1399. #endif
  1400. #ifdef TARGET_LX_WIN_BC
  1401. "\
  1402. -D - Channel number from Level-X Board\n\
  1403. -B - Board name of the Level-X Board\n\
  1404. -U - Board number of the selected Board(only for registry use)\n\
  1405. "
  1406. #endif
  1407. #if defined(TARGET_CPC_ECO) && defined(__WIN32__)
  1408. "\
  1409. -D - Channel name from EMS Board found in cpcconf.ini\n\
  1410. "
  1411. #endif
  1412. #ifdef TARGET_IPC
  1413. "\
  1414. -C - occupy console focus\n\
  1415. "
  1416. #endif
  1417. "\
  1418. -C - enable debug message\n\
  1419. -S - TCP/IP Server mode\n\
  1420. -T - dont use drivers timestamp, use OS time\n\
  1421. -a - advanced - use \"baudrate\" as BTR0/1 value\n\
  1422. -b baudrate (Standard 125)\n\
  1423. -c<id>- use id as debug id, default %d\n\
  1424. -d - debug On\n\
  1425. -f<spec> - specification for receive message filter\n\
  1426. -l<file> Logfilename, logging is enabled/disabled with 'l'\n\
  1427. -p<n> - use portnumber in Servermode, default %d\n\
  1428. -s<n> - send status information every <n> ms\n\
  1429. -t - activate time stamp at start up\n\
  1430. "
  1431. /* -u - use UDP\n\ */
  1432. "-V - Version\n\
  1433. \n\
  1434. for interactive commands press \'?\'\n\
  1435. ";
  1436. fprintf(stderr, "usage: %s options\n", s);
  1437. #ifdef TARGET_LINUX
  1438. fprintf(stderr, usage_text, STDDEV, testCOB, o_portnumber);
  1439. #endif
  1440. #ifdef TARGET_LX_WIN_BC
  1441. fprintf(stderr, usage_text, testCOB, o_portnumber);
  1442. /* erstmal auf die Schnelle */
  1443. fprintf(stderr,"<wait>\n");
  1444. while( !kbhit() ){};
  1445. scan_lx_ini("board.ini", NULL, 0, 0);
  1446. #endif
  1447. #if defined(TARGET_CPC_WIN_BC) || defined(TARGET_AC2_WIN_BC)
  1448. fprintf(stderr, usage_text, testCOB, o_portnumber);
  1449. #endif
  1450. #ifdef TARGET_IPC
  1451. fprintf(stderr, usage_text, testCOB, o_portnumber);
  1452. #endif
  1453. }
  1454. static void online_help(void)
  1455. {
  1456. static char *usage_text = "\
  1457. \t\tOn-line help\n\
  1458. \t\t============\n\
  1459. ? - show On-line help\n\
  1460. l - switch file logging to \"%s\" %s\n\
  1461. i - start data interpreter\n\
  1462. \n\
  1463. a - show data in ascii\n\
  1464. d - show data in dec\n\
  1465. h|H - show data hex\n\
  1466. s - statistic\n\
  1467. t/T - activate/deactivate timestamp display\n\
  1468. w - write message\n\
  1469. f<spec> - specification for receive message filter\n\
  1470. m code mask - change acceptance\n\
  1471. b baud - change bit rate\n\
  1472. \n\
  1473. c - put 'cut'-mark at display\n\
  1474. ^Q/^S start/stop; q - Quit\n\
  1475. ";
  1476. cut_mark();
  1477. fprintf(stderr, usage_text,
  1478. log_file, (log_fp) ? "Off" : "On" /* -l */
  1479. );
  1480. cut_mark();
  1481. }
  1482. static int cut_mark(void)
  1483. {
  1484. static char line[70] = "----------------------------------------\n";
  1485. send_line_cnt = 41;
  1486. if(display_line(line) == -1) {
  1487. return -1;
  1488. }
  1489. send_line_cnt = 0;
  1490. return 0;
  1491. }
  1492. /******************************************
  1493. * quit - check for quit condition
  1494. *
  1495. * RETURNS:
  1496. *
  1497. * nothing
  1498. ********************************************/
  1499. void quit(
  1500. char *line /* settrigger parameter line */
  1501. ) /* idx dont_care RTR id data */
  1502. {
  1503. if(strcmp(line, "uit") == 0) {
  1504. clean_up();
  1505. }
  1506. }
  1507. /**************************************************************************
  1508. *
  1509. * display_line - displays the formatted CAN message
  1510. *
  1511. * changes the \n line end to \r\n
  1512. * !! calling function must provide a puffer at least two bytes
  1513. * longer than the string. !!
  1514. */
  1515. int display_line(char *line)
  1516. {
  1517. int len;
  1518. if(*line == '\0') return 0;
  1519. /* printf(">>%s|%d|", line, */
  1520. /* strlen(line) */
  1521. /* );fflush(stdout); */
  1522. if(o_server) {
  1523. #define use_strlen
  1524. #ifdef use_strlen
  1525. len = strlen(line);
  1526. /* printf("l: %d, ll: %d\n", len, send_line_cnt ); */
  1527. line[len - 1] = '\r';
  1528. line[len ] = '\n';
  1529. line[len + 1] = '\0';
  1530. #else
  1531. line[send_line_cnt - 1] = '\r';
  1532. line[send_line_cnt ] = '\n';
  1533. line[send_line_cnt + 1] = '\0';
  1534. /* printf("ll: %d\n", send_line_cnt ); */
  1535. #endif
  1536. if(o_udpserver) {
  1537. return(sendto(server_fd, (void *)line, send_line_cnt + 1, 0,
  1538. (struct sockaddr *)&fsin, sizeof(fsin) ));
  1539. } else {
  1540. /* return(send(server_fd, (void *)line, send_line_cnt + 1, 0)); */
  1541. #ifdef __WIN32__
  1542. return(send(server_fd, (void *)line, len + 1, 0));
  1543. #else /* __WIN32__ */
  1544. return(send(server_fd, (void *)line, len + 1, MSG_NOSIGNAL));
  1545. #endif /* __WIN32__ */
  1546. }
  1547. } else {
  1548. fprintf(stdout, line); fflush(stdout);
  1549. return 0;
  1550. }
  1551. }
  1552. /* ***********************************************************
  1553. *
  1554. * The function compare_msg compares two CAN-Messages
  1555. * If message2.length == 0, only the ID and the RTR-flag are compared
  1556. *
  1557. * ret=compare_msg(msg1,msg2);
  1558. *
  1559. * return:
  1560. * 0 if messages are unequal , not 0 if messages are equal
  1561. ************************************************************/
  1562. char compare_msg(
  1563. unsigned char dont_care, /* select don't care bytes in the message */
  1564. canmsg_t *eins, /* first message */
  1565. canmsg_t *zwei /* second message */
  1566. )
  1567. {
  1568. int temp2;
  1569. /* compare id */
  1570. if (eins->id != zwei->id) {
  1571. return(0);
  1572. }
  1573. /* compare flags , only RTR */
  1574. if ((eins->flags & MSG_RTR) != (zwei->flags & MSG_RTR))
  1575. {
  1576. return(0);
  1577. }
  1578. /* compare length */
  1579. if (zwei->length == 0) {
  1580. return (1);
  1581. }
  1582. if (eins->length != zwei->length) {
  1583. return (0);
  1584. }
  1585. /* compare data */
  1586. for(temp2 = 0; temp2 < zwei->length; temp2++ ){
  1587. if ( ((dont_care >> temp2) & 0x01) == 1 ) {
  1588. if (eins->data[temp2] != zwei->data[temp2]) {
  1589. return(0);
  1590. }
  1591. }
  1592. }
  1593. return(1);
  1594. } /* end of function compare_msg */
  1595. #define skip_space(p) while(*(p) == ' ' || *(p) == '\t' ) (p)++
  1596. #define skip_word(p) while(*(p) != ' ' && *(p) != '\t' ) (p)++
  1597. /******************************************
  1598. * settrigger - sets the trigger messages
  1599. *
  1600. * RETURNS:
  1601. *
  1602. * nothing
  1603. ********************************************/
  1604. void settrigger(
  1605. char *line /* settrigger parameter line */
  1606. ) /* idx dont_care RTR id data */
  1607. {
  1608. unsigned char *lptr;
  1609. unsigned char *endptr;
  1610. int len = 0;
  1611. int idx = 0;
  1612. /* May be some check is needed if we have a valid and useful message */
  1613. lptr = &line[0];
  1614. skip_space(lptr);
  1615. idx = (unsigned char) strtoul(lptr,&endptr,0);
  1616. if (idx > (MAX_TRIGGER_MESSAGES - 1)) {
  1617. return;
  1618. }
  1619. skip_word(lptr);
  1620. skip_space(lptr);
  1621. /* don't care byte */
  1622. care_mask[idx] = (unsigned char) strtol(lptr,&endptr,0);
  1623. skip_word(lptr);
  1624. skip_space(lptr);
  1625. /* RTR */
  1626. if(*lptr == 'r' || *lptr == 'R') {
  1627. triggermessage[idx].flags=MSG_RTR;
  1628. skip_word(lptr);
  1629. } else {
  1630. triggermessage[idx].flags=0;
  1631. }
  1632. skip_space(lptr);
  1633. /* ID */
  1634. triggermessage[idx].id = (unsigned int)strtoul(lptr, &endptr, 0);
  1635. while( lptr != endptr ) {
  1636. lptr = endptr;
  1637. triggermessage[idx].data[len] = (unsigned char)strtol(lptr, &endptr, 0);
  1638. if(lptr != endptr) {
  1639. len++;
  1640. }
  1641. if(len == 8) {
  1642. break; /* only 8 data bytes! */
  1643. }
  1644. }
  1645. triggermessage[idx].length = len;
  1646. }
  1647. /*************************************************************
  1648. *
  1649. * add_bits - add the message's bits to the global bit counter
  1650. *
  1651. * returns: nothing
  1652. *
  1653. **************************************************************/
  1654. void add_bits (unsigned char u8_flags,unsigned char u8_dlc) {
  1655. if ((u8_flags & MSG_EXT) == 1) {
  1656. u32_bits += 65; /* 47 + 18 */
  1657. } else {
  1658. u32_bits += 47; /* Source for 47: User Manual CANChat */
  1659. }
  1660. if ((u8_flags & MSG_RTR) == 0) {
  1661. u32_bits += 8 * u8_dlc;
  1662. }
  1663. }
  1664. # ifdef TARGET_LINUX
  1665. /*************************************************************
  1666. * alarmhandler - calculates the bus load and set the global bus load
  1667. * variable to the latest value
  1668. *
  1669. * this function is called by sigalrm every sample period ( o_period)
  1670. **********************************************************/
  1671. void alarmhandler (int signo) {
  1672. f_busload =
  1673. (float) u32_bits * 100 / (float) (1000000 / o_period * o_bitrate * 1000);
  1674. u32_bits = 0;
  1675. #ifdef CONFIG_SK
  1676. if( !lifecount--) exit();
  1677. #endif
  1678. }
  1679. # endif /* TARGET_LINUX */