当前位置:网站首页>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]);
}
}
边栏推荐
- [turn] explain awk (1)__ Awk Basics_ Options_ Program segment parsing and examples
- SPI primary key generation strategy for shardingsphere JDBC
- CORS request principle
- Tongweb customs clearance guidelines
- The reason why the process cannot be shut down after a spark job is executed and the solution
- 13 cancelendevent of a flowable end event and compensationthrowing of a compensation event
- 为什么那么多人讨厌A-Spice
- Leetcode- intersection of two arrays - simple
- Pod libwebp error reporting solution
- MySQL custom function
猜你喜欢
Missing tag identification in cots RFID systems: bringing the gap between theory and Practice
ArrayList loop removes the pit encountered
3. Postman easy to use
Mongodb Multi - field Aggregation group by
Source code analysis of ArrayList
MongoDB 多字段聚合Group by
Pod libwebp error reporting solution
Sentinel series hot spot current limiting
Mongodb multi field aggregation group by
arrayList && linkedList
随机推荐
Interrupt processing
Source code analysis of ArrayList
AUTOSAR实战教程pdf版
Leetcode longest harmonic subsequence simple
Missing tag identification in cots RFID systems: bringing the gap between theory and Practice
php 分布式事务 原理详解
Add attributes in storyboard and Xib (fillet, foreground...) Ibinspectable and ibdesignable
Explanation of sentinel series' features, composition and deployment
FusionPBX 安装 —— 筑梦之路
Power simple of leetcode-3
Concurrent programming -- source code analysis of thread pool
Sentinel series introduction to service flow restriction
Concurrent programming -- what is threading?
Leetcode- student attendance record i- simple
Current limiting and fusing of gateway gateway in Spirng cloud
Sentinel series integrates Nacos and realizes dynamic flow control
ffmpeg 下载后缀为.m3u8的视频文件
Shardingsphere JDBC < bind table > avoid join Cartesian product
Leetcode- longest continuous increasing sequence - simple
Lamda expression