1 /* $OpenBSD: usps.c,v 1.12 2024/05/23 03:21:09 jsg Exp $ */ 2 3 /* 4 * Copyright (c) 2011 Yojiro UO <yuo@nui.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 /* Driver for usb smart power strip FX-5204PS */ 20 21 #include <sys/param.h> 22 #include <sys/systm.h> 23 #include <sys/malloc.h> 24 #include <sys/device.h> 25 #include <sys/sensors.h> 26 27 #include <dev/usb/usb.h> 28 #include <dev/usb/usbdi.h> 29 #include <dev/usb/usbdevs.h> 30 31 #ifdef USPS_DEBUG 32 int uspsdebug = 0; 33 #define DPRINTFN(n, x) do { if (uspsdebug > (n)) printf x; } while (0) 34 #else 35 #define DPRINTFN(n, x) 36 #endif 37 38 #define DPRINTF(x) DPRINTFN(0, x) 39 40 #define USPS_UPDATE_TICK 1 /* sec */ 41 #define USPS_TIMEOUT 1000 /* ms */ 42 #define USPS_INTR_TICKS 50 /* ms */ 43 44 /* protocol */ 45 #define USPS_CMD_START 0x01 46 #define USPS_CMD_VALUE 0x20 47 #define USPS_CMD_GET_FIRMWARE 0xc0 48 #define USPS_CMD_GET_SERIAL 0xc1 49 #define USPS_CMD_GET_VOLTAGE 0xb0 50 #define USPS_CMD_GET_TEMP 0xb4 51 #define USPS_CMD_GET_FREQ 0xa1 52 #define USPS_CMD_GET_UNK0 0xa2 53 54 #define USPS_MODE_WATTAGE 0x10 55 #define USPS_MODE_CURRENT 0x30 56 57 #define FX5204_NUM_PORTS 4 58 59 struct usps_port_sensor { 60 struct ksensor ave; 61 struct ksensor min; 62 struct ksensor max; 63 int vave, vmin, vmax; 64 }; 65 66 struct usps_softc { 67 struct device sc_dev; 68 struct usbd_device *sc_udev; 69 struct usbd_interface *sc_iface; 70 struct usbd_pipe *sc_ipipe; 71 int sc_isize; 72 struct usbd_xfer *sc_xfer; 73 uint8_t sc_buf[16]; 74 uint8_t *sc_intrbuf; 75 76 uint16_t sc_flag; 77 78 /* device info */ 79 uint8_t sc_firmware_version[2]; 80 uint32_t sc_device_serial; 81 82 /* sensor framework */ 83 struct usps_port_sensor sc_port_sensor[FX5204_NUM_PORTS]; 84 struct usps_port_sensor sc_total_sensor; 85 struct ksensor sc_voltage_sensor; 86 struct ksensor sc_frequency_sensor; 87 struct ksensor sc_temp_sensor; 88 struct ksensor sc_serial_sensor; 89 struct ksensordev sc_sensordev; 90 struct sensor_task *sc_sensortask; 91 92 int sc_count; 93 }; 94 95 struct usps_port_pkt { 96 uint8_t header; /* should be 0x80 */ 97 uint16_t seq; 98 uint8_t padding[5]; 99 uint16_t port[4]; 100 } __packed; /* 16 byte length struct */ 101 102 static const struct usb_devno usps_devs[] = { 103 { USB_VENDOR_FUJITSUCOMP, USB_PRODUCT_FUJITSUCOMP_FX5204PS}, 104 }; 105 #define usps_lookup(v, p) usb_lookup(usps_devs, v, p) 106 107 int usps_match(struct device *, void *, void *); 108 void usps_attach(struct device *, struct device *, void *); 109 int usps_detach(struct device *, int); 110 void usps_intr(struct usbd_xfer *, void *, usbd_status); 111 112 usbd_status usps_cmd(struct usps_softc *, uint8_t, uint16_t, uint16_t); 113 usbd_status usps_set_measurement_mode(struct usps_softc *, int); 114 115 void usps_get_device_info(struct usps_softc *); 116 void usps_refresh(void *); 117 void usps_refresh_temp(struct usps_softc *); 118 void usps_refresh_power(struct usps_softc *); 119 void usps_refresh_ports(struct usps_softc *); 120 121 struct cfdriver usps_cd = { 122 NULL, "usps", DV_DULL 123 }; 124 125 const struct cfattach usps_ca = { 126 sizeof(struct usps_softc), usps_match, usps_attach, usps_detach 127 }; 128 129 int 130 usps_match(struct device *parent, void *match, void *aux) 131 { 132 struct usb_attach_arg *uaa = aux; 133 134 if (uaa->iface == NULL || uaa->configno != 1) 135 return UMATCH_NONE; 136 137 if (usps_lookup(uaa->vendor, uaa->product) == NULL) 138 return UMATCH_NONE; 139 140 return (UMATCH_VENDOR_PRODUCT); 141 } 142 143 void 144 usps_attach(struct device *parent, struct device *self, void *aux) 145 { 146 struct usps_softc *sc = (struct usps_softc *)self; 147 struct usb_attach_arg *uaa = aux; 148 usb_interface_descriptor_t *id; 149 usb_endpoint_descriptor_t *ed; 150 int ep_ibulk, ep_obulk, ep_intr; 151 usbd_status err; 152 int i; 153 154 sc->sc_udev = uaa->device; 155 156 #define USPS_USB_IFACE 0 157 158 /* get interface handle */ 159 if ((err = usbd_device2interface_handle(sc->sc_udev, USPS_USB_IFACE, 160 &sc->sc_iface)) != 0) { 161 printf("%s: failed to get interface %d: %s\n", 162 sc->sc_dev.dv_xname, USPS_USB_IFACE, usbd_errstr(err)); 163 return; 164 } 165 166 /* find endpoints */ 167 ep_ibulk = ep_obulk = ep_intr = -1; 168 id = usbd_get_interface_descriptor(sc->sc_iface); 169 for (i = 0; i < id->bNumEndpoints; i++) { 170 ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i); 171 if (ed == NULL) { 172 printf("%s: failed to get endpoint %d descriptor\n", 173 sc->sc_dev.dv_xname, i); 174 return; 175 } 176 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 177 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) 178 ep_ibulk = ed->bEndpointAddress; 179 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT && 180 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) 181 ep_obulk = ed->bEndpointAddress; 182 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN && 183 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT){ 184 ep_intr = ed->bEndpointAddress; 185 sc->sc_isize = UGETW(ed->wMaxPacketSize); 186 } 187 } 188 189 if (ep_intr == -1) { 190 printf("%s: no data endpoint found\n", sc->sc_dev.dv_xname); 191 return; 192 } 193 194 usps_get_device_info(sc); 195 strlcpy(sc->sc_sensordev.xname, sc->sc_dev.dv_xname, 196 sizeof(sc->sc_sensordev.xname)); 197 198 /* attach sensor */ 199 sc->sc_voltage_sensor.type = SENSOR_VOLTS_AC; 200 sc->sc_frequency_sensor.type = SENSOR_FREQ; 201 sc->sc_temp_sensor.type = SENSOR_TEMP; 202 sc->sc_serial_sensor.type = SENSOR_INTEGER; 203 sensor_attach(&sc->sc_sensordev, &sc->sc_voltage_sensor); 204 sensor_attach(&sc->sc_sensordev, &sc->sc_frequency_sensor); 205 sensor_attach(&sc->sc_sensordev, &sc->sc_temp_sensor); 206 sensor_attach(&sc->sc_sensordev, &sc->sc_serial_sensor); 207 208 sc->sc_serial_sensor.value = sc->sc_device_serial; 209 strlcpy(sc->sc_serial_sensor.desc, "unit serial#", 210 sizeof(sc->sc_serial_sensor.desc)); 211 212 /* 213 * XXX: the device has mode of par port sensor, Watt of Ampair. 214 * currently only watt mode is selected. 215 */ 216 usps_set_measurement_mode(sc, USPS_MODE_WATTAGE); 217 for (i = 0; i < FX5204_NUM_PORTS; i++) { 218 sc->sc_port_sensor[i].ave.type = SENSOR_WATTS; 219 sc->sc_port_sensor[i].min.type = SENSOR_WATTS; 220 sc->sc_port_sensor[i].max.type = SENSOR_WATTS; 221 sensor_attach(&sc->sc_sensordev, &sc->sc_port_sensor[i].ave); 222 sensor_attach(&sc->sc_sensordev, &sc->sc_port_sensor[i].min); 223 sensor_attach(&sc->sc_sensordev, &sc->sc_port_sensor[i].max); 224 (void)snprintf(sc->sc_port_sensor[i].ave.desc, 225 sizeof(sc->sc_port_sensor[i].ave.desc), 226 "port#%d (average)", i); 227 (void)snprintf(sc->sc_port_sensor[i].min.desc, 228 sizeof(sc->sc_port_sensor[i].min.desc), 229 "port#%d (min)", i); 230 (void)snprintf(sc->sc_port_sensor[i].max.desc, 231 sizeof(sc->sc_port_sensor[i].max.desc), 232 "port#%d (max)", i); 233 } 234 235 sc->sc_total_sensor.ave.type = SENSOR_WATTS; 236 sc->sc_total_sensor.min.type = SENSOR_WATTS; 237 sc->sc_total_sensor.max.type = SENSOR_WATTS; 238 sensor_attach(&sc->sc_sensordev, &sc->sc_total_sensor.ave); 239 sensor_attach(&sc->sc_sensordev, &sc->sc_total_sensor.min); 240 sensor_attach(&sc->sc_sensordev, &sc->sc_total_sensor.max); 241 (void)snprintf(sc->sc_total_sensor.ave.desc, 242 sizeof(sc->sc_total_sensor.ave.desc), "total (average)"); 243 (void)snprintf(sc->sc_total_sensor.min.desc, 244 sizeof(sc->sc_total_sensor.ave.desc), "total (min)"); 245 (void)snprintf(sc->sc_total_sensor.max.desc, 246 sizeof(sc->sc_total_sensor.ave.desc), "total (max)"); 247 248 sc->sc_sensortask = sensor_task_register(sc, usps_refresh, 249 USPS_UPDATE_TICK); 250 if (sc->sc_sensortask == NULL) { 251 printf(", unable to register update task\n"); 252 goto fail; 253 } 254 255 printf("%s: device#=%d, firmware version=V%02dL%02d\n", 256 sc->sc_dev.dv_xname, sc->sc_device_serial, 257 sc->sc_firmware_version[0], 258 sc->sc_firmware_version[1]); 259 260 sensordev_install(&sc->sc_sensordev); 261 262 /* open interrupt endpoint */ 263 sc->sc_intrbuf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK); 264 if (sc->sc_intrbuf == NULL) 265 goto fail; 266 err = usbd_open_pipe_intr(sc->sc_iface, ep_intr, 267 USBD_SHORT_XFER_OK, &sc->sc_ipipe, sc, sc->sc_intrbuf, 268 sc->sc_isize, usps_intr, USPS_INTR_TICKS); 269 if (err) { 270 printf("%s: could not open intr pipe %s\n", 271 sc->sc_dev.dv_xname, usbd_errstr(err)); 272 goto fail; 273 } 274 275 DPRINTF(("usps_attach: complete\n")); 276 return; 277 278 fail: 279 if (sc->sc_ipipe != NULL) 280 usbd_close_pipe(sc->sc_ipipe); 281 if (sc->sc_xfer != NULL) 282 usbd_free_xfer(sc->sc_xfer); 283 if (sc->sc_intrbuf != NULL) 284 free(sc->sc_intrbuf, M_USBDEV, sc->sc_isize); 285 } 286 287 int 288 usps_detach(struct device *self, int flags) 289 { 290 struct usps_softc *sc = (struct usps_softc *)self; 291 int i, rv = 0, s; 292 293 usbd_deactivate(sc->sc_udev); 294 295 s = splusb(); 296 if (sc->sc_ipipe != NULL) { 297 usbd_close_pipe(sc->sc_ipipe); 298 if (sc->sc_intrbuf != NULL) 299 free(sc->sc_intrbuf, M_USBDEV, sc->sc_isize); 300 sc->sc_ipipe = NULL; 301 } 302 if (sc->sc_xfer != NULL) 303 usbd_free_xfer(sc->sc_xfer); 304 splx(s); 305 306 wakeup(&sc->sc_sensortask); 307 sensordev_deinstall(&sc->sc_sensordev); 308 sensor_detach(&sc->sc_sensordev, &sc->sc_voltage_sensor); 309 sensor_detach(&sc->sc_sensordev, &sc->sc_frequency_sensor); 310 sensor_detach(&sc->sc_sensordev, &sc->sc_temp_sensor); 311 sensor_detach(&sc->sc_sensordev, &sc->sc_serial_sensor); 312 for (i = 0; i < FX5204_NUM_PORTS; i++) { 313 sensor_detach(&sc->sc_sensordev, &sc->sc_port_sensor[i].ave); 314 sensor_detach(&sc->sc_sensordev, &sc->sc_port_sensor[i].min); 315 sensor_detach(&sc->sc_sensordev, &sc->sc_port_sensor[i].max); 316 } 317 sensor_detach(&sc->sc_sensordev, &sc->sc_total_sensor.ave); 318 sensor_detach(&sc->sc_sensordev, &sc->sc_total_sensor.min); 319 sensor_detach(&sc->sc_sensordev, &sc->sc_total_sensor.max); 320 321 if (sc->sc_sensortask != NULL) 322 sensor_task_unregister(sc->sc_sensortask); 323 324 return (rv); 325 } 326 327 usbd_status 328 usps_cmd(struct usps_softc *sc, uint8_t cmd, uint16_t val, uint16_t len) 329 { 330 usb_device_request_t req; 331 usbd_status err; 332 333 req.bmRequestType = UT_READ_VENDOR_DEVICE; 334 req.bRequest = cmd; 335 USETW(req.wValue, val); 336 USETW(req.wIndex, 0); 337 USETW(req.wLength, len); 338 339 err = usbd_do_request(sc->sc_udev, &req, &sc->sc_buf); 340 if (err) { 341 printf("%s: could not issue sensor cmd: %s\n", 342 sc->sc_dev.dv_xname, usbd_errstr(err)); 343 return (EIO); 344 } 345 346 return (0); 347 } 348 349 usbd_status 350 usps_set_measurement_mode(struct usps_softc *sc, int mode) 351 { 352 usb_device_request_t req; 353 usbd_status err; 354 355 req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 356 req.bRequest = USPS_CMD_START; 357 USETW(req.wValue, 0); 358 USETW(req.wIndex, 0); 359 USETW(req.wLength, 0); 360 361 err = usbd_do_request(sc->sc_udev, &req, &sc->sc_buf); 362 if (err) { 363 printf("%s: fail to set sensor mode: %s\n", 364 sc->sc_dev.dv_xname, usbd_errstr(err)); 365 return (EIO); 366 } 367 368 req.bRequest = USPS_CMD_VALUE; 369 USETW(req.wValue, mode); 370 371 err = usbd_do_request(sc->sc_udev, &req, &sc->sc_buf); 372 if (err) { 373 printf("%s: could not set sensor mode: %s\n", 374 sc->sc_dev.dv_xname, usbd_errstr(err)); 375 return (EIO); 376 } 377 378 return (0); 379 } 380 381 void 382 usps_intr(struct usbd_xfer *xfer, void *priv, usbd_status status) 383 { 384 struct usps_softc *sc = priv; 385 struct usps_port_pkt *pkt; 386 struct usps_port_sensor *ps; 387 int i, total; 388 389 if (usbd_is_dying(sc->sc_udev)) 390 return; 391 392 if (status != USBD_NORMAL_COMPLETION) { 393 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) 394 return; 395 if (status == USBD_STALLED) 396 usbd_clear_endpoint_stall_async(sc->sc_ipipe); 397 return; 398 } 399 400 /* process intr packet */ 401 if (sc->sc_intrbuf == NULL) 402 return; 403 404 pkt = (struct usps_port_pkt *)sc->sc_intrbuf; 405 406 total = 0; 407 for (i = 0; i < FX5204_NUM_PORTS; i++) { 408 ps = &sc->sc_port_sensor[i]; 409 if (sc->sc_count == 0) 410 ps->vmax = ps->vmin = pkt->port[i]; 411 if (pkt->port[i] > ps->vmax) 412 ps->vmax = pkt->port[i]; 413 if (pkt->port[i] < ps->vmin) 414 ps->vmin = pkt->port[i]; 415 ps->vave = 416 (ps->vave * sc->sc_count + pkt->port[i])/(sc->sc_count +1); 417 total += pkt->port[i]; 418 } 419 420 /* calculate ports total */ 421 ps = &sc->sc_total_sensor; 422 if (sc->sc_count == 0) 423 ps->vmax = ps->vmin = total; 424 if (total > ps->vmax) 425 ps->vmax = total; 426 if (total < ps->vmin) 427 ps->vmin = total; 428 ps->vave = (ps->vave * sc->sc_count + total)/(sc->sc_count +1); 429 430 sc->sc_count++; 431 } 432 433 void 434 usps_get_device_info(struct usps_softc *sc) 435 { 436 int serial; 437 438 /* get Firmware version */ 439 usps_cmd(sc, USPS_CMD_GET_FIRMWARE, 0, 2); 440 sc->sc_firmware_version[0] = 441 (sc->sc_buf[0]>>4) * 10 + (sc->sc_buf[0] & 0xf); 442 sc->sc_firmware_version[1] = 443 (sc->sc_buf[1]>>4) * 10 + (sc->sc_buf[1] & 0xf); 444 445 /* get device serial number */ 446 usps_cmd(sc, USPS_CMD_GET_SERIAL, 0, 3); 447 448 serial = 0; 449 serial += ((sc->sc_buf[0]>>4) * 10 + (sc->sc_buf[0] & 0xf)) * 10000; 450 serial += ((sc->sc_buf[1]>>4) * 10 + (sc->sc_buf[1] & 0xf)) * 100; 451 serial += ((sc->sc_buf[2]>>4) * 10 + (sc->sc_buf[2] & 0xf)); 452 sc->sc_device_serial = serial; 453 } 454 455 void 456 usps_refresh(void *arg) 457 { 458 struct usps_softc *sc = arg; 459 460 usps_refresh_temp(sc); 461 usps_refresh_power(sc); 462 usps_refresh_ports(sc); 463 } 464 465 void 466 usps_refresh_ports(struct usps_softc *sc) 467 { 468 int i; 469 struct usps_port_sensor *ps; 470 471 /* update port values */ 472 for (i = 0; i < FX5204_NUM_PORTS; i++) { 473 ps = &sc->sc_port_sensor[i]; 474 ps->ave.value = ps->vave * 1000000; 475 ps->min.value = ps->vmin * 1000000; 476 ps->max.value = ps->vmax * 1000000; 477 } 478 479 /* update total value */ 480 ps = &sc->sc_total_sensor; 481 ps->ave.value = ps->vave * 1000000; 482 ps->min.value = ps->vmin * 1000000; 483 ps->max.value = ps->vmax * 1000000; 484 485 sc->sc_count = 0; 486 } 487 488 void 489 usps_refresh_temp(struct usps_softc *sc) 490 { 491 int temp; 492 493 if (usps_cmd(sc, USPS_CMD_GET_TEMP, 0, 2) != 0) { 494 DPRINTF(("%s: temperature data read error\n", 495 sc->sc_dev.dv_xname)); 496 sc->sc_temp_sensor.flags |= SENSOR_FINVALID; 497 return; 498 } 499 temp = (sc->sc_buf[1] << 8) + sc->sc_buf[0]; 500 sc->sc_temp_sensor.value = (temp * 10000) + 273150000; 501 sc->sc_temp_sensor.flags &= ~SENSOR_FINVALID; 502 } 503 504 void 505 usps_refresh_power(struct usps_softc *sc) 506 { 507 int v; 508 uint val; 509 uint64_t f; 510 511 /* update source voltage */ 512 if (usps_cmd(sc, USPS_CMD_GET_VOLTAGE, 0, 1) != 0) { 513 DPRINTF(("%s: voltage data read error\n", sc->sc_dev.dv_xname)); 514 sc->sc_voltage_sensor.flags |= SENSOR_FINVALID; 515 return; 516 } 517 518 v = sc->sc_buf[0] * 1000000; 519 sc->sc_voltage_sensor.value = v; 520 sc->sc_voltage_sensor.flags &= ~SENSOR_FINVALID; 521 522 /* update source frequency */ 523 if (usps_cmd(sc, USPS_CMD_GET_FREQ, 0, 8) != 0) { 524 DPRINTF(("%s: frequency data read error\n", 525 sc->sc_dev.dv_xname)); 526 sc->sc_frequency_sensor.flags |= SENSOR_FINVALID; 527 return; 528 } 529 530 if (sc->sc_buf[7] == 0 && sc->sc_buf[6] == 0) { 531 /* special case */ 532 f = 0; 533 } else { 534 val = (sc->sc_buf[1] << 8) + sc->sc_buf[0]; 535 if (val == 0) { 536 /* guard against "division by zero" */ 537 sc->sc_frequency_sensor.flags |= SENSOR_FINVALID; 538 return; 539 } 540 f = 2000000L; 541 f *= 1000000L; 542 f /= val; 543 } 544 545 sc->sc_frequency_sensor.value = f; 546 sc->sc_frequency_sensor.flags &= ~SENSOR_FINVALID; 547 } 548