Skip to content

Commit 590a48f

Browse files
authored
Merge pull request #1325 from jimklimov/libusb-signed-char
LibUSB related code - revise for bit-maths with signed char
2 parents 6d7b236 + 20da521 commit 590a48f

File tree

8 files changed

+122
-17
lines changed

8 files changed

+122
-17
lines changed

drivers/blazer_usb.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,7 @@ void upsdrv_initups(void)
684684
* This should allow automatic application of the workaround */
685685
ret = usb_get_string(udev, 0, 0, (usb_ctrl_charbuf)tbuf, sizeof(tbuf));
686686
if (ret >= 4) {
687-
langid = tbuf[2] | (tbuf[3] << 8);
687+
langid = (unsigned char)tbuf[2] | ((unsigned char)tbuf[3] << 8);
688688
upsdebugx(1, "First supported language ID: 0x%x (please report to the NUT maintainer!)", langid);
689689
}
690690
}

drivers/libshut.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ static int shut_control_msg(
334334

335335
/* Data portability */
336336
/* realign packet data according to Endianess */
337-
#define BYTESWAP(in) (((in & 0xFF) << 8) + ((in & 0xFF00) >> 8))
337+
#define BYTESWAP(in) ((((uint16_t)in & 0x00FF) << 8) + (((uint16_t)in & 0xFF00) >> 8))
338338
static void align_request(struct shut_ctrltransfer_s *ctrl)
339339
{
340340
#if (defined (WORDS_BIGENDIAN)) && (WORDS_BIGENDIAN)
@@ -893,7 +893,7 @@ static unsigned char shut_checksum(
893893
unsigned char chk=0;
894894

895895
for(i=0; i<bufsize; i++)
896-
chk^=buf[i];
896+
chk ^= (unsigned char)buf[i];
897897

898898
upsdebugx (4, "shut_checksum: %02x", chk);
899899
return chk;

drivers/libusb0.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ static int libusb_open(usb_dev_handle **udevp,
377377

378378
upsdebug_hex(3, "HID descriptor, method 1", buf, 9);
379379

380-
rdlen1 = (uint8_t)buf[7] | ((uint8_t)buf[8] << 8);
380+
rdlen1 = ((uint8_t)buf[7]) | (((uint8_t)buf[8]) << 8);
381381
}
382382

383383
if (rdlen1 < -1) {
@@ -407,7 +407,7 @@ static int libusb_open(usb_dev_handle **udevp,
407407
) {
408408
p = (usb_ctrl_char *)&iface->extra[i];
409409
upsdebug_hex(3, "HID descriptor, method 2", p, 9);
410-
rdlen2 = (uint8_t)p[7] | ((uint8_t)p[8] << 8);
410+
rdlen2 = ((uint8_t)p[7]) | (((uint8_t)p[8]) << 8);
411411
break;
412412
}
413413
}

drivers/libusb1.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,9 @@ static int nut_libusb_open(libusb_device_handle **udevp,
141141
#if (defined HAVE_LIBUSB_DETACH_KERNEL_DRIVER) || (defined HAVE_LIBUSB_DETACH_KERNEL_DRIVER_NP)
142142
int retries;
143143
#endif
144-
int rdlen1, rdlen2; /* report descriptor length, method 1+2 */
144+
/* libusb-1.0 usb_ctrl_charbufsize is uint16_t and we
145+
* want the rdlen vars signed - so taking a wider type */
146+
int32_t rdlen1, rdlen2; /* report descriptor length, method 1+2 */
145147
USBDeviceMatcher_t *m;
146148
libusb_device **devlist;
147149
ssize_t devcount = 0;
@@ -159,7 +161,7 @@ static int nut_libusb_open(libusb_device_handle **udevp,
159161

160162
/* report descriptor */
161163
unsigned char rdbuf[MAX_REPORT_SIZE];
162-
int rdlen;
164+
int32_t rdlen;
163165

164166
/* libusb base init */
165167
if (libusb_init(NULL) < 0) {
@@ -425,7 +427,7 @@ static int nut_libusb_open(libusb_device_handle **udevp,
425427

426428
upsdebug_hex(3, "HID descriptor, method 1", buf, 9);
427429

428-
rdlen1 = buf[7] | (buf[8] << 8);
430+
rdlen1 = ((uint8_t)buf[7]) | (((uint8_t)buf[8]) << 8);
429431
}
430432

431433
if (rdlen1 < -1) {
@@ -450,7 +452,7 @@ static int nut_libusb_open(libusb_device_handle **udevp,
450452
if (i+9 <= if_desc->extra_length && if_desc->extra[i] >= 9 && if_desc->extra[i+1] == 0x21) {
451453
p = &if_desc->extra[i];
452454
upsdebug_hex(3, "HID descriptor, method 2", p, 9);
453-
rdlen2 = p[7] | (p[8] << 8);
455+
rdlen2 = ((uint8_t)p[7]) | (((uint8_t)p[8]) << 8);
454456
break;
455457
}
456458
}

drivers/nutdrv_qx.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3058,7 +3058,7 @@ void upsdrv_initups(void)
30583058
ret = usb_get_string(udev, 0, 0,
30593059
(usb_ctrl_charbuf)tbuf, sizeof(tbuf));
30603060
if (ret >= 4) {
3061-
langid = tbuf[2] | (tbuf[3] << 8);
3061+
langid = ((uint8_t)tbuf[2]) | (((uint8_t)tbuf[3]) << 8);
30623062
upsdebugx(1,
30633063
"First supported language ID: 0x%x "
30643064
"(please report to the NUT maintainer!)",

drivers/riello_usb.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,9 @@ static int cypress_setfeatures()
9595

9696
/* Write features report */
9797
ret = usb_control_msg(udev, USB_ENDPOINT_OUT + USB_TYPE_CLASS + USB_RECIP_INTERFACE,
98-
0x09, /* HID_REPORT_SET = 0x09 */
99-
0 + (0x03 << 8), /* HID_REPORT_TYPE_FEATURE */
100-
0, (usb_ctrl_charbuf) bufOut, 0x5, 1000);
98+
0x09, /* HID_REPORT_SET = 0x09 */
99+
0 + (0x03 << 8), /* HID_REPORT_TYPE_FEATURE */
100+
0, (usb_ctrl_charbuf) bufOut, 0x5, 1000);
101101

102102
if (ret <= 0) {
103103
upsdebugx(3, "send: %s", ret ? nut_usb_strerror(ret) : "error");
@@ -197,7 +197,7 @@ static int Get_USB_Packet(uint8_t *buffer)
197197
}
198198

199199
/* copy to buffer */
200-
size = inBuf[0] & 0x07;
200+
size = (unsigned char)(inBuf[0]) & 0x07;
201201
if (size)
202202
memcpy(buffer, &inBuf[1], size);
203203

drivers/tripplite_usb.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -743,10 +743,11 @@ static int soft_shutdown(void)
743743
static int hard_shutdown(void)
744744
{
745745
int ret;
746-
char buf[256], cmd_N[]="N\0x", cmd_K[] = "K\0";
746+
unsigned char buf[256], cmd_N[]="N\0x", cmd_K[] = "K\0";
747747

748-
cmd_N[2] = offdelay;
749-
cmd_N[1] = offdelay >> 8;
748+
/* FIXME: Assumes memory layout / endianness? */
749+
cmd_N[2] = (unsigned char)(offdelay & 0x00FF);
750+
cmd_N[1] = (unsigned char)(offdelay >> 8);
750751
upsdebugx(3, "hard_shutdown(offdelay=%d): N", offdelay);
751752

752753
ret = send_cmd(cmd_N, sizeof(cmd_N), buf, sizeof(buf));

tests/getvaluetest.c

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
*
1111
* Copyright (C)
1212
* 2021 Nick Briggs <[email protected]>
13+
* 2022 Jim Klimov <[email protected]>
1314
*
1415
* This program is free software; you can redistribute it and/or modify
1516
* it under the terms of the GNU General Public License as published by
@@ -34,6 +35,7 @@
3435
#include <stdlib.h>
3536
#include <string.h>
3637
#include "hidtypes.h"
38+
#include "usb-common.h"
3739
#include "common.h"
3840

3941
void GetValue(const unsigned char *Buf, HIDData_t *pData, long *pValue);
@@ -125,6 +127,106 @@ static int RunBuiltInTests(char *argv[]) {
125127
exitStatus = 1;
126128
}
127129
}
130+
131+
/* Emulate rdlen calculations in libusb{0,1}.c or
132+
* langid calculations in nutdrv_qx.c; in these
133+
* cases we take two bytes (cast from usb_ctrl_char
134+
* type, may be signed depending on used API version)
135+
* from the protocol buffer, and build a platform
136+
* dependent representation of a two-byte word.
137+
*/
138+
usb_ctrl_char bufC[2];
139+
signed char bufS[2];
140+
unsigned char bufU[2];
141+
int rdlen;
142+
143+
/* Example from issue https://github.com/networkupstools/nut/issues/1261
144+
* where resulting length 0x01a9 should be "425" but ended up "-87" */
145+
bufC[0] = (usb_ctrl_char)0xa9;
146+
bufC[1] = (usb_ctrl_char)0x01;
147+
148+
bufS[0] = (signed char)0xa9;
149+
bufS[1] = (signed char)0x01;
150+
151+
bufU[0] = (unsigned char)0xa9;
152+
bufU[1] = (unsigned char)0x01;
153+
154+
/* Check different conversion methods and hope current build CPU,
155+
* C implementation etc. do not mess up bit-shifting vs rotation,
156+
* zeroing high bits, int type width extension et al. If something
157+
* is mismatched below, the production NUT code may need adaptations
158+
* for that platform to count stuff correctly!
159+
*/
160+
printf("\nTesting bit-shifting approaches used in codebase to get 2-byte int lengths from wire bytes:\n");
161+
printf("(Expected correct value is '425', incorrect '-87' or other)\n");
162+
163+
#define REPORT_VERDICT(expected) { if (expected) { printf(" - PASS\n"); } else { printf(" - FAIL\n"); exitStatus = 1; } }
164+
165+
rdlen = bufC[0] | (bufC[1] << 8);
166+
printf(" * reference: no casting, usb_ctrl_char :\t%d\t(depends on libusb API built against)", rdlen);
167+
REPORT_VERDICT (rdlen == 425 || rdlen == -87)
168+
169+
rdlen = bufS[0] | (bufS[1] << 8);
170+
printf(" * reference: no casting, signed char :\t%d\t(expected '-87' here)", rdlen);
171+
REPORT_VERDICT (rdlen == -87)
172+
173+
rdlen = bufU[0] | (bufU[1] << 8);
174+
printf(" * reference: no casting, unsigned char :\t%d\t(expected '425')", rdlen);
175+
REPORT_VERDICT (rdlen == 425)
176+
177+
178+
rdlen = (uint8_t)bufC[0] | ((uint8_t)bufC[1] << 8);
179+
printf(" * uint8_t casting, usb_ctrl_char :\t%d", rdlen);
180+
REPORT_VERDICT (rdlen == 425)
181+
182+
rdlen = (uint8_t)bufS[0] | ((uint8_t)bufS[1] << 8);
183+
printf(" * uint8_t casting, signed char :\t%d", rdlen);
184+
REPORT_VERDICT (rdlen == 425)
185+
186+
rdlen = (uint8_t)bufU[0] | ((uint8_t)bufU[1] << 8);
187+
printf(" * uint8_t casting, unsigned char :\t%d", rdlen);
188+
REPORT_VERDICT (rdlen == 425)
189+
190+
191+
rdlen = ((uint8_t)bufC[0]) | (((uint8_t)bufC[1]) << 8);
192+
printf(" * uint8_t casting with parentheses, usb_ctrl_char :\t%d", rdlen);
193+
REPORT_VERDICT (rdlen == 425)
194+
195+
rdlen = ((uint8_t)bufS[0]) | (((uint8_t)bufS[1]) << 8);
196+
printf(" * uint8_t casting with parentheses, signed char :\t%d", rdlen);
197+
REPORT_VERDICT (rdlen == 425)
198+
199+
rdlen = ((uint8_t)bufU[0]) | (((uint8_t)bufU[1]) << 8);
200+
printf(" * uint8_t casting with parentheses, unsigned char :\t%d", rdlen);
201+
REPORT_VERDICT (rdlen == 425)
202+
203+
204+
rdlen = ((uint16_t)(bufC[0]) & 0x00FF) | (((uint16_t)(bufC[1]) & 0x00FF) << 8);
205+
printf(" * uint16_t casting with 8-bit mask, usb_ctrl_char :\t%d", rdlen);
206+
REPORT_VERDICT (rdlen == 425)
207+
208+
rdlen = ((uint16_t)(bufS[0]) & 0x00FF) | (((uint16_t)(bufS[1]) & 0x00FF) << 8);
209+
printf(" * uint16_t casting with 8-bit mask, signed char :\t%d", rdlen);
210+
REPORT_VERDICT (rdlen == 425)
211+
212+
rdlen = ((uint16_t)(bufU[0]) & 0x00FF) | (((uint16_t)(bufU[1]) & 0x00FF) << 8);
213+
printf(" * uint16_t casting with 8-bit mask, unsigned char :\t%d", rdlen);
214+
REPORT_VERDICT (rdlen == 425)
215+
216+
217+
rdlen = 256 * (uint8_t)(bufC[1]) + (uint8_t)(bufC[0]);
218+
printf(" * uint8_t casting with multiplication, usb_ctrl_char :\t%d", rdlen);
219+
REPORT_VERDICT (rdlen == 425)
220+
221+
rdlen = 256 * (uint8_t)(bufS[1]) + (uint8_t)(bufS[0]);
222+
printf(" * uint8_t casting with multiplication, signed char :\t%d", rdlen);
223+
REPORT_VERDICT (rdlen == 425)
224+
225+
rdlen = 256 * (uint8_t)(bufU[1]) + (uint8_t)(bufU[0]);
226+
printf(" * uint8_t casting with multiplication, unsigned char :\t%d", rdlen);
227+
REPORT_VERDICT (rdlen == 425)
228+
229+
128230
return (exitStatus);
129231
}
130232

0 commit comments

Comments
 (0)