libpandac  0.0.0
A library designed for a comm.ai Panda.
usb.h
1 /*
2  Author: Matt Bunting
3  Copyright (c) 2020 Arizona Board of Regents
4  All rights reserved.
5 
6  Permission is hereby granted, without written agreement and without
7  license or royalty fees, to use, copy, modify, and distribute this
8  software and its documentation for any purpose, provided that the
9  above copyright notice and the following two paragraphs appear in
10  all copies of this software.
11 
12  IN NO EVENT SHALL THE ARIZONA BOARD OF REGENTS BE LIABLE TO ANY PARTY
13  FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14  ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15  IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
16  SUCH DAMAGE.
17 
18  THE ARIZONA BOARD OF REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES,
19  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20  AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER
21  IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION
22  TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23 
24  */
25 
26 #ifndef PANDA_USB_H
27 #define PANDA_USB_H
28 
29 #include <iostream>
30 //#include <libusb.h> // for macOS catalina
31 #include <libusb-1.0/libusb.h>
32 #include <vector>
33 
34 #include <string>
35 
36 #include "mogi/thread.h"
37 #include "pandadefinitions.h"
38 
39 #define TIMEOUT (0) // For libusb, in ms
40 #define NUM_CAN_PACKETS_PER_TRANSFER (4) // I've had luck with a value of 4, but failure at 3 or less
41 #define BYTES_PER_CAN_PACKET (16)
42 #define BYTES_PER_UART_TRANSFER (64)
43 
44 namespace Panda {
45  class Usb;
46 
47  typedef enum {
48  MODE_SYNCHRONOUS,
49  MODE_ASYNCHRONOUS,
50  MODE_ISOCHRONOUS
51  } UsbMode;
52 
53  const char* safetyModelToString( int safetyModel );
54  const char* carHarnessStatusToString( int car_harness_status);
55  const char* faultStatusToString( int fault_status);
56  std::string faultsToString( int faults );
57  const char* usbPowerModeToString( int usb_power_mode );
58  void printPandaHealth( const PandaHealth& health );
59 
60  class UsbListener {
61  private:
62  friend class Usb;
63  protected:
64  // Overload the following for new incoming data
65  // You MUST be efficient in this call, or you will hold up the notification thread.
66  // Suggestion is to copy data, then return. Spin up a new thread if you must
67  //virtual void newDataNotification(char* buffer, size_t bufferLength) = 0;
68 
69  virtual void notificationUartRead(char* buffer, size_t bufferLength) {};
70  virtual void notificationUartWrite() {};
71 
72  virtual void notificationCanRead(char* buffer, size_t bufferLength) {};
73  virtual void notificationCanWrite() {};
74 
75  public:
76  virtual ~UsbListener() = 0;
77 
78  };
79 
80  class Usb : protected Mogi::Thread {
81  public:
82  Usb(UsbMode mode = MODE_ASYNCHRONOUS);
83  ~Usb();
84 
85  // initialize the USB panda interface
86  void initialize();
87 
88  // This uses an observer/listener pattern, listeners are notified when new USB info comes in.
89  // - Note, make sure Usb::stopRecording() is called BEFORE listener destruction, otherwise a
90  // segfault will most likely happen
91  // This is the ONLY way to read data fromt he USB device in this class
92  void addObserver( UsbListener* listener );
93 
94 
95  // Send USB data
96  // Returns 0 on success, otherwise failure
97  int sendCanData( unsigned char* buffer, int length);
98  // Invokes a read request for CAN data:
99  void requestCanData();
100  void requestUartData();
101 
102  // uart write and read, for GPS
103  bool hasGpsSupport();
104  void uartWrite(const char* buffer, int length);
105 // int uartRead(unsigned char* buffer);
106  void uartPurge();
107  void canPurge();
108  void setUartBaud(int uart, int baud);
109  void setUartParity(int uart, int parity);
110 
111  // Panda device handling:
112  void setEspPower(bool enable);
113  void espReset(int uart, int bootmode=0);
114  void getPandaSerial(unsigned char* serial16);
115  void setCanLoopback( int enable );
116  void getFirmware(unsigned char* firmware128 );
117  unsigned char getHardware();
118  struct tm getRtc();
119  void setSafetyMode(uint16_t mode);
120  void sendHeartBeat(); // Call more that 0.5 Hz to geet talking to panda
121  void setPowerSaveEnable( bool enable );
122 
123  // The standard getters/setters:
124  void setOperatingMode(UsbMode mode);
125  const char* getModeAsString() const;
126  std::string getUsbSerialNumber() { return serialNumber; };
127  void getHealth( PandaHealth* health );
128 
129  // Begin the USB data transfering, for reading:
130  void startRecording();
131  void stopRecording();
132 
133  private:
134  bool hasGps;
135  UsbMode mode;
136 
137  std::vector<UsbListener*> listeners;
138  char serialNumber[200]; // Stores the Panda's usb serial number
139  char pandaSerial[16]; // Panda's serial number
140 
141  // libusb variables:
142  //struct libusb_device *device;
143  struct libusb_device_handle *handler;
144  //struct libusb_transfer *transfer;
145  //struct libusb_transfer *outgoingTransfer;
146 // struct libusb_transfer *uartTransfer;
147 
148  unsigned char bufferSynchronousCan[BYTES_PER_CAN_PACKET*NUM_CAN_PACKETS_PER_TRANSFER]; // I think Rahul wanted this at 16, which seems a bit small...
149  unsigned char bufferSynchronousUart[BYTES_PER_UART_TRANSFER];
150  unsigned int bufferLengthSynchronousUart;
151 
152  //void asyncControlTransferUart();
153  void sendModedUart();
154 
155  // Opens the panda, a USB device with manufacture string "comma.ai"
156  int openDeviceByManufacturer(libusb_device **devs, const char* manufacturerName);
157 
158  // Functions called by callbacks for completed transfer processing
159  void processNewCanRead(char* buffer, size_t length);
160  void processNewCanSend(size_t length);
161  void processNewUartRead(char* buffer, size_t length);
162  void processNewUartSend(size_t length);
163 
164 
165  // callback function for libusb when thread is running
166  static void transferCallbackReadCan(struct libusb_transfer *transfer);
167  static void transferCallbackSendCan(struct libusb_transfer *transfer);
168  static void transferCallbackReadUart(struct libusb_transfer *transfer);
169  static void transferCallbackSendUart(struct libusb_transfer *transfer);
170 
171  // prints libusb status errors from most libsusb functions
172  static void printError(int status);
173  static void printErrorTransfer(libusb_transfer_status status);
174 
175  // Override from Mogi::Thread
176  void entryAction();
177  void doAction();
178 
179 
180  // Simple handling layers:
181  void sendPandaHardwareSimple(uint8_t requestType, uint8_t request, uint16_t value, uint16_t index);
182  void readPandaHardwareSimple(uint8_t requestType, uint8_t request, unsigned char* buffer, uint16_t length);
183 
184  };
185 
186 }
187 
188 #endif
Handles USB communication and parsing with a comma.ai Panda.
Definition: can.h:38
Abstract class, handles a single thread. Features mutual exclusion and pause/resume.
Definition: thread.h:27
Definition: usb.h:80
Definition: usb.h:60