@@ -85,17 +85,71 @@ channels = can.detect_available_configs('candle')
8585print (channels)
8686```
8787
88+ ### Open multiple channels of a single device
89+
90+ This driver now supports opening multiple channels from the same device in a single ` CandleBus ` instance.
91+
92+ - Pass a list of channels belonging to the same device, e.g. ` ['SERIAL:0', 'SERIAL:1'] ` .
93+ - Alternatively, pass a list of indices with ` serial_number=SERIAL ` .
94+ - A single instance must NOT mix channels from different devices.
95+
96+ ``` python
97+ import can
98+ from candle import CandleBus
99+
100+ # Option A: list of "serial:idx" strings
101+ bus = CandleBus(channel = [' 208233AD5003:0' , ' 208233AD5003:1' ], fd = True , bitrate = 1000000 , data_bitrate = 5000000 , loop_back = True )
102+
103+ # Option B: list of indices with explicit serial number
104+ bus = CandleBus(channel = [0 , 1 ], serial_number = ' 208233AD5003' , fd = True , bitrate = 1000000 , data_bitrate = 5000000 , loop_back = True )
105+
106+ # Send to a specific channel by setting msg.channel
107+ m0 = can.Message(arbitration_id = 0x 100 , data = b ' \x00 ' * 8 , is_fd = True )
108+ m0.channel = 0
109+ bus.send(m0)
110+
111+ m1 = can.Message(arbitration_id = 0x 101 , data = b ' \x01 ' * 8 , is_fd = True )
112+ m1.channel = 1
113+ bus.send(m1)
114+
115+ # Receive frames: msg.channel indicates the source channel
116+ rx = bus.recv(timeout = 0.5 )
117+ print (rx.channel, hex (rx.arbitration_id))
118+
119+ bus.shutdown()
120+ ```
121+
122+ ### Notes on multi-channel behavior
123+
124+ - A single ` CandleBus ` instance manages multiple channels of one device using one device handle.
125+ - ` send() ` routes frames to the target channel based on ` msg.channel ` (int, ` "SERIAL:idx" ` , or ` "idx" ` ).
126+ - ` recv() ` returns ` Message.channel ` set to the source channel number.
127+ - When ` msg.channel ` is not set, ` send() ` defaults to the first managed channel.
128+ - To test multiple devices simultaneously, create one ` CandleBus ` per device.
129+
130+ ### Backward compatibility
131+
132+ - Existing single-channel usage is unchanged; ` channel=0 ` or ` channel='SERIAL:0' ` still works.
133+ - ` can.detect_available_configs('candle') ` continues to report channels as ` serial:idx ` strings.
134+ - The stress test ` python -m candle.stress ` (single-channel) remains compatible.
135+
88136### Performance
89137
90- The communication layer is implemented based on pybind11 with libusb. You can run the following script to evaluate the performance.
138+ The communication layer is implemented based on pybind11 with libusb. You can run the following scripts to evaluate the performance.
91139
140+ For single-channel performance:
92141``` shell
93142python -m candle.stress
94143```
95144
145+ For multi-channel and multi-device performance and correctness verification:
146+ ``` shell
147+ python -m candle.stress_multichannel
148+ ```
149+
96150## Reference
97151
98152- [ linux gs_usb driver] ( https://github.com/torvalds/linux/blob/master/drivers/net/can/usb/gs_usb.c )
99153- [ python gs_usb driver] ( https://github.com/jxltom/gs_usb )
100154- [ candleLight firmware] ( https://github.com/candle-usb/candleLight_fw )
101- - [ candle_api] ( https://github.com/BIRLab/candle_api )
155+ - [ candle_api] ( https://github.com/BIRLab/candle_api )
0 commit comments