Skip to content

Commit 471d638

Browse files
committed
pybricks.iodevices.PUPDevice: Restore passive device detection.
Fixes pybricks/support#1162
1 parent a3bbc90 commit 471d638

File tree

1 file changed

+52
-1
lines changed

1 file changed

+52
-1
lines changed

pybricks/iodevices/pb_type_iodevices_pupdevice.c

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,23 +27,64 @@ typedef struct _iodevices_PUPDevice_obj_t {
2727
pb_type_device_obj_base_t device_base;
2828
// Mode used when initiating awaitable read. REVISIT: This should be stored
2929
// on the awaitable instead, as extra context. For now, it is safe since
30-
// concurrent reads with the same sensor are not permitten.
30+
// concurrent reads with the same sensor are not permitted.
3131
uint8_t last_mode;
32+
// ID of a passive device, if any.
33+
pbdrv_legodev_type_id_t passive_id;
3234
} iodevices_PUPDevice_obj_t;
3335

36+
/**
37+
* Tests if the given device is a passive device and stores ID.
38+
*
39+
* @param [in] self The PUP device.
40+
* @param [in] port_in The port.
41+
* @return True if passive device, false otherwise.
42+
*/
43+
STATIC bool init_passive_pup_device(iodevices_PUPDevice_obj_t *self, mp_obj_t port_in) {
44+
pb_module_tools_assert_blocking();
45+
pbio_port_id_t port = pb_type_enum_get_value(port_in, &pb_enum_type_Port);
46+
pbdrv_legodev_type_id_t candidates[] = {
47+
PBDRV_LEGODEV_TYPE_ID_ANY_DC_MOTOR,
48+
PBDRV_LEGODEV_TYPE_ID_LPF2_LIGHT,
49+
};
50+
for (uint8_t i = 0; i < MP_ARRAY_SIZE(candidates); i++) {
51+
if (pbdrv_legodev_get_device(port, &candidates[i], &self->device_base.legodev) == PBIO_SUCCESS) {
52+
self->passive_id = candidates[i];
53+
return true;
54+
}
55+
}
56+
return false;
57+
}
58+
3459
// pybricks.iodevices.PUPDevice.__init__
3560
STATIC mp_obj_t iodevices_PUPDevice_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
3661
PB_PARSE_ARGS_CLASS(n_args, n_kw, args,
3762
PB_ARG_REQUIRED(port));
3863

3964
iodevices_PUPDevice_obj_t *self = mp_obj_malloc(iodevices_PUPDevice_obj_t, type);
65+
66+
// For backwards compatibility, allow class to be used with passive devices.
67+
if (init_passive_pup_device(self, port_in)) {
68+
return MP_OBJ_FROM_PTR(self);
69+
}
70+
71+
// Initialize any UART PUP device.
4072
pb_type_device_init_class(&self->device_base, port_in, PBDRV_LEGODEV_TYPE_ID_ANY_LUMP_UART);
73+
self->passive_id = PBDRV_LEGODEV_TYPE_ID_LPF2_UNKNOWN_UART;
4174
return MP_OBJ_FROM_PTR(self);
4275
}
4376

4477
// pybricks.iodevices.PUPDevice.info
4578
STATIC mp_obj_t iodevices_PUPDevice_info(mp_obj_t self_in) {
4679
iodevices_PUPDevice_obj_t *self = MP_OBJ_TO_PTR(self_in);
80+
81+
// Passive devices only have an ID.
82+
if (self->passive_id != PBDRV_LEGODEV_TYPE_ID_LPF2_UNKNOWN_UART) {
83+
mp_obj_t info_dict = mp_obj_new_dict(1);
84+
mp_obj_dict_store(info_dict, MP_ROM_QSTR(MP_QSTR_id), MP_OBJ_NEW_SMALL_INT(self->passive_id));
85+
return info_dict;
86+
}
87+
4788
pbdrv_legodev_info_t *info;
4889
pb_assert(pbdrv_legodev_get_info(self->device_base.legodev, &info));
4990

@@ -107,6 +148,11 @@ STATIC mp_obj_t iodevices_PUPDevice_read(size_t n_args, const mp_obj_t *pos_args
107148
iodevices_PUPDevice_obj_t, self,
108149
PB_ARG_REQUIRED(mode));
109150

151+
// Passive devices don't support reading.
152+
if (self->passive_id != PBDRV_LEGODEV_TYPE_ID_LPF2_UNKNOWN_UART) {
153+
pb_assert(PBIO_ERROR_INVALID_OP);
154+
}
155+
110156
self->last_mode = mp_obj_get_int(mode_in);
111157

112158
// We can re-use the same code as for specific sensor types, only the mode
@@ -127,6 +173,11 @@ STATIC mp_obj_t iodevices_PUPDevice_write(size_t n_args, const mp_obj_t *pos_arg
127173
PB_ARG_REQUIRED(mode),
128174
PB_ARG_REQUIRED(data));
129175

176+
// Passive devices don't support writing.
177+
if (self->passive_id != PBDRV_LEGODEV_TYPE_ID_LPF2_UNKNOWN_UART) {
178+
pb_assert(PBIO_ERROR_INVALID_OP);
179+
}
180+
130181
// Get requested mode.
131182
uint8_t mode = mp_obj_get_int(mode_in);
132183

0 commit comments

Comments
 (0)