当前位置:网站首页>Introduction to USB learning (5) -- looking back, the man was in the dim light

Introduction to USB learning (5) -- looking back, the man was in the dim light

2022-06-13 06:03:00 You must know this and do it yourself

        Get to know USB equipment , How to implement host and in our program USB Equipment communication , The first thing you think about is development USB Device driver , After all, we see a lot of USB Before using the device, you need to install the driver , Begin to contact USB When the equipment , I think so too , For this reason, I also specially studied windows Drive programming , As one can imagine , All the way down, it was hard , Need not say oneself . later , I saw libusb, It's a lot of people looking for him , Suddenly look back , The man was in the dim light .
        libusb Website is https://libusb.info/, He is a very good USB Open source software for device communication , The parameters of his interface function and USB Technology itself is closely linked , Easy to understand , Cross platform , Whether it's windows still linux still android You can use , It's user space code , No additional driver support is required , Download the source code from the official website , Follow the instructions to build the dynamic library or static library of the corresponding platform , Add it to our own project to call the interface function in the library , Implement host to USB Device communication . In use , There are several points to note , One is libusb stay windows The platform is built on hid or winusb On the basis of , our USB The device should support hid Or general USB The equipment , If it is universal USB equipment , Should be enabled in the system winusb drive ( As mentioned earlier ), And then in our libusb You can call “libusb_open_device_with_vid_pid” Function to open the device , It can be seen from this that ,libusb stay windows Driver support is also required in the environment , It's just windows in , These drivers are already installed , It took me a long time to figure this out . Second, in linux In the system ,libusb It's based on linux Device file system (sysfs) Above (2.6 The kernel will be like this in the future ), And nowadays there are many linux By default, all versions contain libusb Components ( use libusb Can query ), So on such a system, you only need to include the header file of the library , You can build your application with a link library , This makes libusb stay linux More powerful functions on the platform . Three is in android On the platform, if libusb And USB Device communication , Can pass android Of jni Mechanism generation so library , And then in java Call in program so The method of the function in the library uses libusb, But it still needs apk Get and use... In the program USB Device permissions , Otherwise, the communication fails , This is especially important .

attach 1:libusb Function description ( come from https://blog.csdn.net/wince_lover/article/details/70337809)

1 libusb_init
The function prototype :int libusb_init(libusb_context **ctx);
Functional specifications : This function performs libusb The initialization , Must be called first .
Parameter description :ctx Usually set NULL
Return value :0 success , Not 0 Failure


2 libusb_exit
The function prototype :void  libusb_exit(libusb_context *ctx);
Functional specifications : and libusb_init Use in pairs , Release the corresponding resources .
Parameter description :ctx Usually set NULL


3 libusb_has_capability
The function prototype :int libusb_has_capability(uint32_t capability);
Functional specifications : Judge whether the current library supports a function
Parameter description :capability The value range of is enum libusb_capability In the definition of .
          LIBUSB_CAP_HAS_CAPABILITY libus Library        API Whether it works , This item usually returns 1
          LIBUSB_CAP_HAS_HOTPLUG     Whether hot plug is supported
          LIBUSB_CAP_HAS_HID_ACCESS Whether access is supported HID equipment , Without user intervention
          LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER Whether it supports releasing the default driver in the kernel, that is, you can call libusb_detach_kernel_driver To release the kernel driver
Return value : Not 0 Support ,0 I won't support it


4 libusb_hotplug_register_callback
The function prototype :int LIBUSB_CALL libusb_hotplug_register_callback(libusb_context *ctx,        libusb_hotplug_event events,libusb_hotplug_flag flags,        int vendor_id, int product_id,
                                                int dev_class,        libusb_hotplug_callback_fn cb_fn,        void *user_data,libusb_hotplug_callback_handle *handle);
Functional specifications : Register callback function , Respond to hot plug events .
Parameter description :ctx Usually it is NULL
          events Events to respond to , Parameter is LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED Device insertion event LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT Device unplugging event , It's fine too LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED|LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT Indicates that the plug-in event is responded to at the same time
          flags If 0, The registered callback function will be called only when plugging occurs , If LIBUSB_HOTPLUG_ENUMERATE, The device has been inserted before initialization , It will also call the registered destroy function .
          vendor_id Need to be monitored VID, Only specified VID Plug and unplug your device , The callback function is called . Set to LIBUSB_HOTPLUG_MATCH_ANY, No judgment VID
          product_id Need to be monitored PID, If set to LIBUSB_HOTPLUG_MATCH_ANY, No judgment PID
          dev_class   Equipment to be monitored class, If set to LIBUSB_HOTPLUG_MATCH_ANY, No judgment class. Notice the class Is with the libusb_device_descriptor Of class matching , instead of libusb_interface_descriptor Of class
          cb_fn Pointer to the callback function   The callback function is defined as int LIBUSB_CALL hotplug_callback(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data)
          user_data Pointer to user data Corresponds to... In the callback function user_data
          handle     Handle  
Return value :0 success , Not 0 Failure
Be careful : Do not call a possible blocking operation in a callback function , Otherwise, it may cause libusb Other functions of failed to execute , Do not call... In a callback function libusb_claim_interface Wait for the operation , There's a risk of failure


5 libusb_hotplug_deregister_callback
The function prototype :void LIBUSB_CALL libusb_hotplug_deregister_callback(libusb_context *ctx,libusb_hotplug_callback_handle handle);
Parameter description : Cancellation libusb_hotplug_register_callback Function registration callback function
Parameter description :ctx Usually it is NULL          
          handle   libusb_hotplug_register_callback Handle returned
Return value : nothing


6 libusb_handle_events  
The function prototype : int LIBUSB_CALL libusb_handle_events(libusb_context *ctx);  
Functional specifications : Handle any pending events in blocking mode .
Parameter description :ctx Usually it is NULL  
Return value :0 success , Not 0 Failure
Be careful :1 call libusb_handle_events The thread of , Do not perform blocking operations , Otherwise, it may cause libusb Other functions failed to execute
2 If a hot plug event is registered , You must call this function in a loop For example, the following code, such as how to plug USB equipment , Can't print “device insert”
static int LIBUSB_CALL hotplug_callback(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data)
{
        printf("device insert  \n");   
}  
int main(int argc, char **argv)
{
        libusb_hotplug_callback_handle hp;
        libusb_init (NULL);
        libusb_hotplug_register_callback (NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, LIBUSB_HOTPLUG_ENUMERATE, LIBUSB_HOTPLUG_MATCH_ANY,
                LIBUSB_HOTPLUG_MATCH_ANY, 0, hotplug_callback, NULL, &hp);
        while(1);
        libusb_hotplug_deregister_callback(hp);
}  
It must be changed to the following code , Plug USB Just can have “device insert” Information about  
static int LIBUSB_CALL hotplug_callback(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data)
{
        printf("device insert  \n");   
}  
int main(int argc, char **argv)
{
        libusb_hotplug_callback_handle hp;
        libusb_init (NULL);
        libusb_hotplug_register_callback (NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, LIBUSB_HOTPLUG_ENUMERATE, LIBUSB_HOTPLUG_MATCH_ANY,
                LIBUSB_HOTPLUG_MATCH_ANY, 0, hotplug_callback, NULL, &hp);
        while(1)
        {
                libusb_handle_events(NULL);
        }
        libusb_hotplug_deregister_callback(hp);
}  
 
7   libusb_open_device_with_vid_pid
The function prototype :libusb_device_handle * LIBUSB_CALL libusb_open_device_with_vid_pid(        libusb_context *ctx, uint16_t vendor_id, uint16_t product_id); 
The functionality : adopt VID and PID Open one USB equipment , And return the device handle libusb_device_handle The pointer to
Parameter description :ctx Usually it is NULL 
          vendor_id The equipment VID
          product_id The equipment PID
Return value : Successfully returns libusb_device_handle The pointer to , Failure to return NULL


8 libusb_open
The function prototype :int LIBUSB_CALL libusb_open(libusb_device *dev, libusb_device_handle **handle);
The functionality : adopt libusb_device The pointer of opens a USB equipment , And return the device handle libusb_device_handle The pointer to
Parameter description :dev libusb_device The pointer to
          handle Used to return the device handle libusb_device_handle The pointer to
Return value :0 success , Not 0 Failure


9 libusb_close
The function prototype :void LIBUSB_CALL libusb_close(libusb_device_handle *dev_handle);
The functionality : close libusb_open perhaps libusb_open_device_with_vid_pid Open the device
Parameter description :dev_handle   call libusb_open perhaps libusb_open_device_with_vid_pid Device handle returned libusb_device_handle The pointer to
Return value : nothing


10 libusb_get_device_list
The function prototype :ssize_t LIBUSB_CALL libusb_get_device_list(libusb_context *ctx,        libusb_device ***list);
The functionality : Get the current device list
The functionality :ctx Usually it is NULL 
          list USB The equipment list
Return value :0 success , Not 0 Failure


11 libusb_free_device_list
The function prototype :void LIBUSB_CALL libusb_free_device_list(libusb_device **list,        int unref_devices);
The functionality : Release the list of previously used devices
Parameter description :list Pointer to the device list to be released
          unref_devices If this parameter is set to 1 The reference count for each device in the list is decremented 1
Return value : nothing
notes : Here is the sample code :
        libusb_device **devs;
        ssize_t cnt;
        int i;
        libusb_init (NULL); 
        cnt = libusb_get_device_list(NULL, &devs);
        for(i=0;i<cnt;i++)
        {
                PrintUsbDec(devs[i]);
        }
        libusb_free_device_list(devs, 1);
        
12 libusb_get_device_descriptor
The function prototype :int LIBUSB_CALL libusb_get_device_descriptor(libusb_device *dev,        struct libusb_device_descriptor *desc);        
The functionality : obtain USB Device descriptor of the device
Parameter description :dev libusb_device The pointer to , Is the device to read
                  desc Pointer to the device descriptor , The structure used to bring back the device descriptor
Return value :0 success , Not 0 Failure
Be careful : This function copies the structure of the device descriptor to desc Address to
therefore , The following usage is wrong
struct libusb_device_descriptor *desc;
libusb_get_device_descriptor(dev,desc);
The correct way to write it is
struct libusb_device_descriptor desc;
libusb_get_device_descriptor(dev,&desc);        


13 libusb_get_config_descriptor
The function prototype :int LIBUSB_CALL libusb_get_config_descriptor(libusb_device *dev,        uint8_t config_index, struct libusb_config_descriptor **config);
The functionality : Gets the configuration descriptor of the specified device
Parameter description :dev libusb_device The pointer to , Is the device to read
          config_index Configure the index of the descriptor ( One USB The device may have multiple configurations )
          config Pointer to the configuration descriptor , Used to bring back the device descriptor
Return value :0 success , Not 0 Failure


14 libusb_free_config_descriptor  
The function prototype :void LIBUSB_CALL libusb_free_config_descriptor(        struct libusb_config_descriptor *config); 
The functionality : Release configuration descriptor
Parameter description :config Configuration descriptor to release
Return value : nothing
Be careful : use libusb_get_config_descriptor Must be called after obtaining the configuration descriptor        libusb_free_config_descriptor Release , Otherwise, memory leakage will occur .


15  libusb_control_transfer
The function prototype :int LIBUSB_CALL libusb_control_transfer(libusb_device_handle *dev_handle,        uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
              unsigned char *data, uint16_t wLength, unsigned int timeout);  
Parameter description :dev_handle libusb_device_handle The pointer to
                  request_type      D7=0 Host to device , =1 Device to host ;
                            D6D5 =00 Standard request command , 01 Class request command ,10 User defined commands ,11 Reserved values
                            D4D3D2D1D0= 0 Indicates that the recipient is a device ,1 Indicates that the receiver is an interface ,2 Indicates that the recipient is the endpoint ,3 Indicates that the recipient is another , Other values remain
                             This parameter is determined by enum libusb_request_recipient 、enum libusb_request_type 、enum libusb_endpoint_direction Combine
          bRequest       The sequence number of the command ( It's just a command ); All commands are passed to the device in the form of different coding values ,bRequest It means USB The encoded value of the command . It can be USB Standard order , You can also customize commands
                         The standard request command is defined in enum libusb_standard_request
          Value         2 Bytes , The parameter used to transmit the current request , Varies from request to request .
          Index     The index field is also 2 Bytes , It describes the interface number
          data      Pointer to the data to be transmitted , No need to transmit data , Set to NULL
          wLength     Length of data . When the command does not need to transmit data , This field is set to 0
          timeout   Set the number of milliseconds for timeout , If you set 0, Never time out
notes :USB Standard request command :
1. To obtain state Get Status (00H)
    A:[To Device] Get the status of the device :
   *. position 0: Self powered (0 Indicates bus power supply ;1 Indicates self powered ).
   *. position 1: Remote wakeup (0 Remote wakeup is not supported ;1 Indicates remote wake-up ).
   *. position 2~15: Retain .
   *. Generally, bus power supply is selected , Remote wake up is not supported , So the returned data is 0x0000.
   B:[To Interface] Get the status of the interface :
   *. Interface status 16 All bits and bytes are reserved , So the returned data is 0x0000.
   C:[To Endpoint] Get the status of the endpoint :
   *. position 0:Halt(0 Indicates that the endpoint allows ;1 Indicates that the endpoint is prohibited ).
   *. position 1~15: Retain ( Reset to 0).
2. Clear properties Clear Feature (01H)
   A:[To Device] Clear the remote wake-up function of the device , And return an empty packet .
   B:[To Endpoint] End point of lifting ban .
3. Set up features Set Feature (03H)
   A:[To Device] Set the remote wake-up function of the device , And return an empty packet .
   B:[To Endpoint] Disable endpoint .
4. Set the address Set Address (05H)
   A: Set the device address .
5. Get descriptor Get Descriptor (06H)
   A:[To Device] Get device descriptor :
   *. Describe the present USB Version number of the protocol . Device endpoint 0 Of FIFO size .USB The equipment ID Number, etc. .
   B:[To Configuration] Get configuration descriptor :
   *. describe USB Number of equipment interfaces and whether there is self power supply capacity, etc .
   C:[To Interface] Get interface descriptor :
   *. Describe the endpoint 0 Number of physical endpoints other than .
   D:[To Endpoint] Get endpoint descriptor :
   *. Describe the endpoint 0 The transmission type and maximum packet size of each endpoint and the transmission direction of the endpoint (IN/OUT).
6. Set descriptor ( Optional , Cannot update ) Set Descriptor (07H)
7. Get configuration information Get Configuration (08H)
8. Set configuration Set Configuration (09H)
A:[To Configuration] Set the configuration descriptor .
B:[To Interface] Set interface descriptor .
C:[To Endpoint] Set endpoint descriptor .
9. Get interface information Get Interface (0AH)    
10. Set interface Set Interface (0BH)
11.SYNCH_FRAME(0CH)
The synchronization frame used by the device to set and report an endpoint .


16 libusb_kernel_driver_active
The function prototype :int LIBUSB_CALL libusb_kernel_driver_active(libusb_device_handle *dev,int interface_number);
The functionality : Determines whether the kernel driver for the specified interface has been activated . If a kernel driver is active ,libusb_claim_interface The call will fail
Parameter description :dev call libusb_open perhaps libusb_open_device_with_vid_pid Back to libusb_device_handle The handle of
                  interface_number Interface number , This corresponds to the interface descriptor bInterfaceNumber
Return value :1 Has activated , Not 1 No activation


17 libusb_detach_kernel_driver
The function prototype :int LIBUSB_CALL libusb_detach_kernel_driver(libusb_device_handle *dev,int interface_number);
The functionality : Uninstall the kernel driver of the specified interface . If a kernel driver is active , This function must be called first , Call again libusb_claim_interface
Parameter description :dev call libusb_open perhaps libusb_open_device_with_vid_pid Back to libusb_device_handle The handle of
                  interface_number Interface number , This corresponds to the interface descriptor bInterfaceNumber
Return value :0 success , Not 0 Failure


18 libusb_claim_interface
The function prototype :int LIBUSB_CALL libusb_claim_interface(libusb_device_handle *dev,        int interface_number);
The functionality : Apply for an interface for the specified device
Parameter description :dev call libusb_open perhaps libusb_open_device_with_vid_pid Back to libusb_device_handle The handle of
                  interface_number Interface number , This corresponds to the interface descriptor bInterfaceNumber
Return value :0 success , Not 0 Failure


19 libusb_release_interface
The function prototype :int LIBUSB_CALL libusb_release_interface(libusb_device_handle *dev,        int interface_number);
The functionality : Apply for an interface for the specified device before releasing , Note that this function just releases the interface , Kernel drivers will not be reloaded
Parameter description :dev call libusb_open perhaps libusb_open_device_with_vid_pid Back to libusb_device_handle The handle of
                  interface_number Interface number , This corresponds to the interface descriptor bInterfaceNumber
Return value :0 success , Not 0 Failure


19 libusb_attach_kernel_driver
The function prototype :int LIBUSB_CALL libusb_attach_kernel_driver(libusb_device_handle *dev,        int interface_number);
The functionality : Load the kernel driver of the specified interface
Parameter description :dev call libusb_open perhaps libusb_open_device_with_vid_pid Back to libusb_device_handle The handle of
                  interface_number Interface number , This corresponds to the interface descriptor bInterfaceNumber
Return value :0 success , Not 0 Failure  


Here is the sample code :
        if(libusb_kernel_driver_active(handle, bInterfaceNumber) == 1) // Determine when the kernel driver loads  
        { 
             
                if(libusb_detach_kernel_driver(handle, bInterfaceNumber) == 0) // Unload the drive , For example, we operate a U disc , Then execute the... In the device file here U The disc will disappear
                {
                         printf("Kernel Driver Detached!");  
                }
         }  
         libusb_claim_interface(handle, bInterfaceNumber);  
         .......... Read and write to the device
         libusb_release_interface(handle, bInterfaceNumber); // Release the requested interface  
         
         libusb_attach_kernel_driver(handle, bInterfaceNumber); // Load the kernel driver ,U The disk will reappear in the device file
        
20 libusb_set_auto_detach_kernel_driver
The function prototype :int LIBUSB_CALL libusb_set_auto_detach_kernel_driver(        libusb_device_handle *dev, int enable);
The functionality : Set to automatically uninstall kernel drivers , Note that the kernel driver will not be uninstalled when this function is called , Just marking . Calling libusb_claim_interface When the kernel driver is uninstalled
           Calling libusb_release_interface Automatically load kernel drivers when
Parameter description :dev call libusb_open perhaps libusb_open_device_with_vid_pid Back to libusb_device_handle The handle of
                  enable  1 Enable the function of automatic unloading ,0 close
Return value :0 success , Not 0 Failure  
for example The following code has the same effect as the above code        
        libusb_set_auto_detach_kernel_driver(handle,1); 
        libusb_claim_interface(handle, bInterfaceNumber);  // Uninstall the kernel driver before requesting the interface
        .......... Read and write to the device
        libusb_release_interface(handle, bInterfaceNumber); // Automatically load the kernel driver after releasing the requested interface  
        
21 libusb_bulk_transfer
The function prototype :int LIBUSB_CALL libusb_bulk_transfer(libusb_device_handle *dev_handle,unsigned char endpoint, unsigned char *data, int length,int *actual_length, unsigned int timeout);
The functionality : perform USB Bulk transfer . This function can handle input and output , Infer the transmission direction according to the direction bit of the endpoint address , This function adopts synchronous mode , Return after data transmission
Parameter description :dev_handle call libusb_open perhaps libusb_open_device_with_vid_pid Back to libusb_device_handle The handle of
                  endpoint Endpoint address The highest bit is 1 Indicates input
                  data      Send or receive buffer pointer
                  length    Buffer length
                  actual_length Bring back the actual transmission length
                  timeout Number of milliseconds timed out ,0 Never time out
Return value :0 success , Not 0 Failure  


22 libusb_clear_halt
The function prototype :int LIBUSB_CALL libusb_clear_halt(libusb_device_handle *dev,        unsigned char endpoint);
The functionality : Clear the endpoint halt/stall state ,libusb_bulk_transfer It is possible to return to LIBUSB_ERROR_PIPE, This is the function that needs to be called
Parameter description :dev call libusb_open perhaps libusb_open_device_with_vid_pid Back to libusb_device_handle The handle of
          endpoint Wrong endpoint address
Return value :0 success , Not 0 Failure   


23 libusb_interrupt_transfer
The function prototype :int LIBUSB_CALL libusb_interrupt_transfer(libusb_device_handle *dev_handle,unsigned char endpoint, unsigned char *data, int length,int *actual_length, unsigned int timeout); 
The functionality : perform USB Interrupt transmission . This function can handle input and output , Infer the transmission direction according to the direction bit of the endpoint address , This function adopts synchronous mode , Return after data transmission
Parameter description :dev_handle call libusb_open perhaps libusb_open_device_with_vid_pid Back to libusb_device_handle The handle of
                  endpoint Endpoint address The highest bit is 1 Indicates input
                  data      Send or receive buffer pointer
                  length    Buffer length
                  actual_length Bring back the actual transmission length
                  timeout Number of milliseconds timed out ,0 Never time out
Return value :0 success , Not 0 Failure                        


24 libusb_set_configuration
The function prototype :int LIBUSB_CALL libusb_set_configuration(libusb_device_handle *dev,int configuration);
The functionality : Set a configuration parameter for the device , Most devices have only one configuration. This function usually does not need to call . When a USB When the device has multiple configurations, it needs to be set
Parameter description :dev   call libusb_open perhaps libusb_open_device_with_vid_pid Back to libusb_device_handle The handle of
                  configuration Configuration parameters , This corresponds to... In the configuration descriptor bConfigurationValue
Return value :0 success , Not 0 Failure  


attach 2:linusb Simple application example

#include <stdio.h>
#include <libusb-1.0/libusb.h>
#include <stdint.h>
#include <string.h>

void processMessage(const uint8_t*);
/*----------------------------------------------------------------------*/
int main(int argc, char*argv[])
{
  int res                      = 0;  /* return codes from libusb functions */
  libusb_device_handle* handle = 0;  /* handle for USB device */
  int kernelDriverDetached     = 0;  /* Set to 1 if kernel driver detached */
  int numBytes                 = 0;  /* Actual bytes transferred. */
  uint8_t buffer[64];                /* 64 byte transfer buffer */

  /* Initialise libusb. */
  res = libusb_init(0);
  if (res != 0)
  {
    fprintf(stderr, "Error initialising libusb.\n");
    return 1;
  }

  /* Get the first device with the matching Vendor ID and Product ID. If
   * intending to allow multiple demo boards to be connected at once, you
   * will need to use libusb_get_device_list() instead. Refer to the libusb
   * documentation for details. */
  handle = libusb_open_device_with_vid_pid(0, 0x04d8, 0x0070);
  if (!handle)
  {
    fprintf(stderr, "Unable to open device.\n");
    return 1;
  }

  /* Check whether a kernel driver is attached to interface #0. If so, we'll 
   * need to detach it.
   */
  if (libusb_kernel_driver_active(handle, 0))
  {
    res = libusb_detach_kernel_driver(handle, 0);
    if (res == 0)
    {
      kernelDriverDetached = 1;
    }
    else
    {
      fprintf(stderr, "Error detaching kernel driver.\n");
      return 1;
    }
  }

  /* Claim interface #0. */
  res = libusb_claim_interface(handle, 0);
  if (res != 0)
  {
    fprintf(stderr, "Error claiming interface.\n");
    return 1;
  }


  /* We can now send and receive messages. For example, set normal mode. */
  memset(buffer, 0, 64);
  buffer[58] = 0;      /* CANCTRL = Normal mode. */
  buffer[60] = 0x02;   /* SPI command = Write.   */
  buffer[61] = 0x0f;   /* Register = CANCTRL     */
  buffer[62] = 0;      /* Data = 0 (normal mode) */
  
  /* Send the message to endpoint 1 with a 100ms timeout. */
  res = libusb_interrupt_transfer(handle, 1, buffer, 64, &numBytes, 100);
  if (res == 0)
  {
    printf("%d bytes transmitted successfully.\n", numBytes);
  }
  else
  {
    fprintf(stderr, "Error sending message to device.\n");
  }


  /* Listen for a message. Note that for a normal application you'll need 
   * to use asynchronous mode because we can't predict when messages will be
   * available. This involves setting up a callback function to handle incoming
   * messages - refer to libusb documentation. */

  /* Wait up to 5 seconds for a message to arrive on endpoint 0x81. */
  res = libusb_interrupt_transfer(handle, 0x81, buffer, 64, &numBytes, 5000);
  if (0 == res)
  {
    if (numBytes == 64)
    {
      processMessage(buffer);
    }
    else
    {
      printf("Received %d bytes, expected 64.\n", numBytes);
    }
  }
  else
  {
    fprintf(stderr, "Error receiving message.\n");
  }

  /* Release interface #0. */
  res = libusb_release_interface(handle, 0);
  if (0 != res)
  {
    fprintf(stderr, "Error releasing interface.\n");
  }

  /* If we detached a kernel driver from interface #0 earlier, we'll now 
   * need to attach it again.  */
  if (kernelDriverDetached)
  {
    libusb_attach_kernel_driver(handle, 0);
  }

  /* Shutdown libusb. */
  libusb_exit(0);

  return 0;
}


/*----------------------------------------------------------------------*/
void processMessage(const uint8_t* buffer)
{
  unsigned index = 0;

  /* Most significant bit set indicates a CAN message is present. */
  while(buffer[index] & 0x80)
  {
    unsigned extendedID = buffer[index] & 0x20;
    unsigned rtr        = buffer[index] & 0x10;
    unsigned dataLength = buffer[index] & 0x0f;
    unsigned canID      = 0;

    ++index;

    if (extendedID)  /* 29 bit identifier */
    {
      canID = buffer[index] << 21;
      ++index;
      canID |= (((buffer[index] & 0xe0 >> 5) | 
            (buffer[index] & 0x03)) << 16);
      ++index;
      canID |= (buffer[index] << 8);
      ++index;
      canID |= (buffer[index]);
      ++index;
    }
    else /* standard 11 bit identifier */
    {
      canID      = buffer[index] << 3;
      ++index;
      canID |= ((buffer[index] >> 1) & 7);
      ++index;
    }

    printf("CAN ID: 0x%x [%s] ", canID,
        extendedID ? "extended" : "standard");

    if (rtr)
    {
      printf("RTR\n");
    }
    else
    {
      unsigned i = 0;
      for (i = 0; i < dataLength; ++i)
      {
        printf("0x%02x ", buffer[index]);
        ++index;
      }
      printf("\n");
    }
  }

  printf("CAN Status:      0x%02x\n", buffer[57]);
  printf("Transmit Errors: %u\n", buffer[55]);
  printf("Receive Errors:  %u\n", buffer[56]);

  /* If the command was read, we have received the result. */
  if (buffer[60] == 0x03)
  {
    printf("Read from register 0x%02x returned 0x%02x\n",
        buffer[61], buffer[62]);
  }
}

原网站

版权声明
本文为[You must know this and do it yourself]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202270558178074.html